思路:
微信小程序获取用户授权后能获取到授权code,
前端调用登录接口传给后端code获取用户openid等信息。
登录接口:通过微信api调用getSessionInfo获取openid等基本信息,
获取成功后判断是否为新用户进行登录/新增用户后登录,
通过jwt生成token与refreshToken,将token与refreshToken存入redis中并设置有效期,然后将token与refreshToken返回给前端。
前端每次调用接口在请求头中传入token。
后端使用shiro自定义filter拦截请求,并解析token进行校验,若token校验失败或者过期则返回固定code给前端。
前端请求收到对应code后调用refreh_token接口传入refreshToken获取新的token。
refreh_token接口:接受到refrehToken参数后进行校验,若校验通过则生成新的token并存入redis;若校验失败或者refrehToken过期则返回失败信息,前端接收到失败的信息后重新调用登录接口进行登录。
以下具体代码:
@GetMapping(“login”)
@ApiOperation(“微信登录”)
public AjaxResult login(String code){
try {
WxMaJscode2SessionResult info = wxMaService.getUserService().getSessionInfo(code);
//这里是通过jdk方式调用微信api
ResultToken token = new ResultToken();
User user= userService.queryByOpenId(info.getOpenid());
if(user==null){
//保存新用户
user=new User ();
user.setOpenId(info.getOpenid());
user.insert(user);
}
token.setUserId(viViuser.getId());
String userToken = getToken(viViuser);
String refreshToken = getRefreshToken(viViuser);
token.setToken(userToken);
token.setRefresh_token(refreshToken);
//存入token与refreshToken并设置过期时间,refresh_toke的过期时间至少为token的两倍以上,这里使用指定前缀+userid作为key,token作为value
redisRepository.setExpire(ViConstants.PREFIX_VI_REDIS_USER_TOKEN+viViuser.getId(),userToken,3600*24);
redisRepository.setExpire(ViConstants.PREFIX_VI_REDIS_USER_REFRESH_TOKEN+viViuser.getId(),refreshToken,3600*24*7);
return AjaxResult.success(token);
} catch (WxErrorException e) {
e.printStackTrace();
return AjaxResult.error(e.getError().getErrorMsg());
}
}
public String getToken(User user) {
String token="";
token= JWT.create().withAudience(String.valueOf(user.getId())).withIssuedAt(new Date())
.sign(Algorithm.HMAC256(ViConstants.PREFIX_VI_TOKEN_SIGNuser.getOpenId()));
return token;
}
public String getRefreshToken(User user) {
String token="";
token= JWT.create().withAudience(String.valueOf(user.getId())).withIssuedAt(new Date())
.sign(Algorithm.HMAC256(ViConstants.PREFIX_VI_REFRESH_TOKEN_SIGN+user.getOpenId()));
return token;
}
JWTFilter:
public class JWTFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
//生成shiro中的token并交给shiro进行登录验证,登录验证过程在userRealm进行重写
AuthenticationToken token = this.createToke