E企盈营销工具技术服务商 热线:4006-838-530

微信小程序认证,微信小程序登录+基于token的身份验证

E企盈直播平台营销卖货系统

官方时序图如下:图里其实说的很清楚了,清理下流程:1.前端调用wx.login()获取code值2.前端通过调用wx.getUserInfo获取iv、rawData、signature、encryptedData等加密数据,传递给后端3.服务器通过code请求api换回session_key和openid4.服务器通过前端给的rawData加获取的session_key使用sha1加密,计算出signature15.比对前端传的signature和自己算出来的signature1是否一致(防止数据不一致)6.用AES算法解密encryptedData里的敏感数据7.拿着敏感数据后做自己的逻辑8.通知前端登陆成功这里只是想拿到用户的openid,则直接1,3就可以做到了。如下:第一步:通过wx.login(微信前端–小程序)接口获取code,将code传到后台注意:code的来源:是用户打开小程序的时候,随机生成的,是腾讯生成的,每个code只能使用一次,因此,理论上这个code是安全的packagecn.wmyskxz.springboot.model.user;/@Author:Yangke@Date:2019/3/3115:52/publicclassWeChatLoginModel{Stringcode;publicStringgetCode(){returncode;}publicvoidsetCode(Stringcode){this.code=code;}}第二步:后台通过code访问微信(腾讯)接口,微信(腾讯)接口返回当前登录的信息:session_key及openid返回的openid是每个用户唯一的,通过这个可以匹配微信(腾讯)的用户跟我们的用户,就是我们后台通过openid来判断这个人是谁,UserController.java微信小程序登录/微信小程序登录登录成功后,将用户身份信息及session_key存入token@parammodel@return/@ResponseBody@PostMapping(“/weChatLogin”)publicSingleResultStringweChatLogin(@RequestBodyWeChatLoginModelmodel){/登录日志:iduseriddatewx_codecreateTimecreatetableloginLog(idvarchar(50)primarykey,userIdvarchar(50),logindatedate,wxcodevarchar(100),createtimedatetime);/SingleResultStringresult=newSingleResultString();//第三步:调用service.weChatLogin(model):后台检查openid是否存在,返回openid对应的用户WeChatLoginResultUserAccountloginResult=service.weChatLogin(model);//第四步:UserAccountuser=loginResult.getUser();if(user==null){result.setCode(0);result.setMessage(“登录失败”);}else{Useru=newUser();u.setId(user.getId());u.setPassword(user.getPassword()==null?user.getWxopenid():user.getPassword());u.setSessionKey(loginResult.getSession_key());Stringtoken=getToken(u);result.setToken(token);result.setCode(1);result.setMessage(“登陆成功”);}returnresult;}其中:就是下面的第三步//调用service.weChatLogin(model)WeChatLoginResultUserAccountloginResult=service.weChatLogin(model);第三步:后台检查openid是否存在,去UserService.java@OverridepublicWeChatLoginResultUserAccountweChatLogin(WeChatLoginModelmodel){WeChatLoginResultUserAccountresult=null;try{//code-openidStringurlFormat=”https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code”;Stringurl=String.format(urlFormat,WeChat.appId,WeChat.secret,model.getCode());Stringjson=WeChat.sendGet(url);//将json字符串转化成对象result=JSON.parseObject(json,WeChatLoginResult.class);if(result.getErrcode()==null){//去数据库检查openId是否存在不存在就新建用户UserAccountuser=userAccount.wechatOpenIdIsExists(result.getOpenid());if(user==null||user.getId()==null){//不存在,就是第一次登录:新建用户信息user=newUserAccount();user.setId(UUID.randomUUID().toString());user.setWxopenid(result.getOpenid());user.setLasttime(newDate());userAccount.insert(user);}else{//如果存在,就不是第一次登录,更新最后登录时间user.setLasttime(newDate());userAccount.updateByPrimaryKeySelective(user);}result.setUser(user);//保存登录日志LoginLoglog=newLoginLog();log.setId(UUID.randomUUID().toString());log.setCreatetime(newDate());log.setLogindate(newDate());log.setUserid(user.getId());log.setWxcode(model.getCode());loginLog.insert(log);}else{System.out.println(json);}}catch(Exceptione){System.out.println(e.getMessage());}returnresult;}去数据库中检查openid是否存在:UserAccountMapper.java@Select(“selectfromuseraccountwherewxOpenId=#{wxOpenId}”)UserAccountwechatOpenIdIsExists(StringwxOpenId);(1)如果不存在:就是该用户的第一次登录,后台数据库新添加一个用户信息如果存在:就不是该用户的第一次登录,以前登陆过,就更新后台数据库中该用户的第一次登录时间(2)返回用户信息第四步:下发token//第四步:UserAccountuser=loginResult.getUser();if(user==null){result.setCode(0);result.setMessage(“登录失败”);}else{Useru=newUser();u.setId(user.getId());//用户如果是第一次登录,那就是没有密码的,这里用openid当做密码u.setPassword(user.getPassword()==null?user.getWxopenid():user.getPassword());u.setSessionKey(loginResult.getSession_key());//利用User.class中的信息生成tokenStringtoken=getToken(u);//下发tokenresult.setToken(token);result.setCode(1);result.setMessage(“登陆成功”);}returnresult;}其中生成token的步骤:BaseController.java利用JWT框架生成tokenpackagecn.wmyskxz.springboot.controllers;importcn.wmyskxz.springboot.model.User;importcom.auth0.jwt.JWT;importcom.auth0.jwt.algorithms.Algorithm;importjava.util.Date;/@Author:Yangke@Date:2019/3/2821:12/publicabstractclassBaseController{protectedStringgetToken(Useruser){Stringtoken=””;token=JWT.create().withKeyId(user.getId()).withIssuer(“www.ikertimes.com”).withIssuedAt(newDate()).withJWTId(“jwt.ikertimes.com”).withClaim(“session_key”,user.getSessionKey()).withAudience(user.getId()).sign(Algorithm.HMAC256(user.getPassword()));returntoken;}}至此,再理一下上面的步骤:(1)微信小程序通过访问wx.login获得一个code,返回给后台(2)后台拿着这个code,调用腾讯的接口,获取到openid、seesion-key等信息,openid是用户唯一的(3)后台拿着openid去数据库中检查,该用户是否是第一次登陆如果是第一次登陆,那么就新建一个用户–UserAcount;如果不是第一次登陆,就修改该用户的最后登录时间不管是不是第一次登录,都有了一个用户(4)然后根据用户的信息利用JWT生成token,下发给微信小程序第五步微信小程序收到token后,存起来第六步微信小程序请求后台微信小程序把token放在请求头中第七步先介绍一个注解:Authorize说明:如果有这个注解,就需要验证tokenpackagecn.wmyskxz.springboot.annotation;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/@Author:Yangke@Date:2019/3/2819:57authorize是判断是否需要token/@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public@interfaceAuthorize{booleanrequired()defaulttrue;}用拦截器,验证tokenpackagecn.wmyskxz.springboot.interceptors;importcn.wmyskxz.springboot.annotation.AllowAnonymous;importcn.wmyskxz.springboot.annotation.Authorize;importcn.wmyskxz.springboot.model.User;importcn.wmyskxz.springboot.service.UserService;importcom.auth0.jwt.JWT;importcom.auth0.jwt.JWTVerifier;importcom.auth0.jwt.algorithms.Algorithm;importcom.auth0.jwt.exceptions.JWTDecodeException;importcom.auth0.jwt.exceptions.JWTVerificationException;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.lang.reflect.Method;/@Author:Yangke@Date:2019/3/2820:00获取token并验证token/publicclassAuthorizationInterceptorimplementsHandlerInterceptor{@AutowiredUserServiceuserService;//拦截器:请求之前preHandle@OverridepublicbooleanpreHandle(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse,Objectobject)throwsException{//如果不是映射到方法直接通过if(!(objectinstanceofHandlerMethod)){returntrue;}HandlerMethodhandlerMethod=(HandlerMethod)object;Methodmethod=handlerMethod.getMethod();//检查是否有passtoken注释,有则跳过认证,注意:其中这个注解多余了if(method.isAnnotationPresent(AllowAnonymous.class)){AllowAnonymouspassToken=method.getAnnotation(AllowAnonymous.class);if(passToken.required()){returntrue;}}//检查有没有需要用户权限的注解//如果有注解Authorize,就需要验证tokenif(method.isAnnotationPresent(Authorize.class)){AuthorizeuserLoginToken=method.getAnnotation(Authorize.class);if(userLoginToken.required()){Stringtoken=httpServletRequest.getHeader(“authorization”);//从http请求头中取出token//执行认证if(token==null){thrownewRuntimeException(“无token,请重新登录”);}//获取token中的useridStringuserId;try{//获取useriduserId=JWT.decode(token).getKeyId();//添加request参数,用于传递useridhttpServletRequest.setAttribute(“currentUser”,userId);//根据userId查询用户信息Useruser=userService.getUserById(userId);if(user==null){thrownewRuntimeException(“用户不存在,请重新登录”);}try{Stringsession_key=JWT.decode(token).getClaim(“session_key”).as(String.class);//添加request参数,用于传递useridhttpServletRequest.setAttribute(“sessionKey”,session_key);}catch(Exceptione){}//验证密码JWTVerifierjwtVerifier=JWT.require(Algorithm.HMAC256(user.getPassword())).build();try{jwtVerifier.verify(token);}catch(JWTVerificationExceptione){thrownewRuntimeException(“401”);}}catch(JWTDecodeExceptionj){thrownewRuntimeException(“401”);}returntrue;}}returntrue;}@OverridepublicvoidpostHandle(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse,Objecto,ModelAndViewmodelAndView)throwsException{}//拦截器:请求之后:afterCompletion@OverridepublicvoidafterCompletion(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse,Objecto,Exceptione)throwsException{}}流程:1、从http请求头中取出tokenStringtoken=httpServletRequest.getHeader(“authorization”);2、如果没有token,抛出异常,请用户登录如果有token,利用JWT从token中取出userid,添加到request参数3、根据userid去后台数据库中查询用户是否存在,如果不存在,抛出异常:用户不存在,请重新登录Useruser=userService.getUserById(userId);这个方法:@OverridepublicUsergetUserById(Stringid){UserAccountu=userAccount.selectByPrimaryKey(id);Useruser=newUser();user.setId(u.getId());user.setPassword(u.getPassword()==null?u.getWxopenid():u.getPassword());user.setUsername(u.getUsername());returnuser;}4、如果用户存在,再利用JWT从token中取出seesion-key,添加到request参数Stringsession_key=JWT.decode(token).getClaim(“session_key”).as(String.class);5、验证密码:因为我生成token的时候,是存了密码的,这个就是检查一下密码对不对验证token里面的密码跟你存的是不是一样JWTVerifierjwtVerifier=JWT.require(Algorithm.HMAC256(user.getPassword())).build();try{jwtVerifier.verify(token);}catch(JWTVerificationExceptione){thrownewRuntimeException(“401”);}6、最终token验证成功,返回true,放行拦截器介绍一下:preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView(这个博主就基本不怎么用了);afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);第八步:request里面有userid,后台就可以识别是对哪个用户做处理

赞(0) 打赏
未经允许不得转载:E企盈小程序开发-热线:4006-838-530 » 微信小程序认证,微信小程序登录+基于token的身份验证
分享到: 更多 (0)
E企盈小程序直播营销卖货系统
E企盈直播平台营销卖货系统

评论 抢沙发

E企盈小程序开发

联系我们联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏