
代码:
public interface TokenManager { /**
* 创建token
* @param userInfo
* @return
*/
String getToken(UserInfo userInfo); /**
* 刷新用户
* @param token
*/
void refreshUserToken(String token); /**
* 用户退出登陆
* @param token
*/
void loginOff(String token); /**
* 获取用户信息
* @param token
* @return
*/
UserInfo getUserInfoByToken(String token); }
具体实现:
@Component
public class RedisTokenManager implements TokenManager { @Autowired
private RedisUtils redisUtils; @Autowired
private GlobalConfig globalConfig; /**
* 创建token
* @param userInfo
* @return
*/
public String getToken(UserInfo userInfo){
//使用uuid作为源token
String token = UUID.randomUUID().toString().replace("-", "");
String token_format=String.format(Constants.TOKEN_FORMAT,token);
redisUtils.set(token_format,userInfo,globalConfig.getTokenExpires());
return token;
} /**
* 刷新用户
* @param token
*/
public void refreshUserToken(String token){
token=String.format(Constants.TOKEN_FORMAT,token);
if(redisUtils.exists(token)){
redisUtils.setExpireTime(token, globalConfig.getTokenExpires());
}
} /**
* 用户退出登陆
* @param token
*/
public void loginOff(String token){
token=String.format(Constants.TOKEN_FORMAT,token);
redisUtils.remove(token);
} /**
* 获取用户信息
* @param token
* @return
*/
public UserInfo getUserInfoByToken(String token){
token=String.format(Constants.TOKEN_FORMAT,token);
if(redisUtils.exists(token)){
return (UserInfo)redisUtils.get(token);
}
return null;
}
}
对TokenManager进行二次封装,每次操作不需要token参数
@Component
public class AuthManager { @Autowired
private TokenManager tokenManager; /**
* 获取请求体
* @return
*/
public HttpServletRequest getRequest(){
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
} /**
* 登录
* @param userInfo
* @return
*/
public String signIn(UserInfo userInfo){
return tokenManager.getToken(userInfo);
} /**
* 获取该访问用户信息
* @return
*/
public UserInfo getUserInfo(){
HttpServletRequest request=getRequest();
String token=request.getAttribute(Constants.USER_TOKEN).toString();
UserInfo userInfo=tokenManager.getUserInfoByToken(token);
if(userInfo==null){
throw new AuthException("该用户已过期", HttpStatus.UNAUTHORIZED.value());
}
return userInfo;
} /**
* 刷新该登录用户,延时
*/
public void refreshUserInfo(){
HttpServletRequest request=getRequest();
String token=request.getAttribute(Constants.USER_TOKEN).toString();
tokenManager.refreshUserToken(token);
} /**
* 注销该访问用户
*/
public void loginOff(){
HttpServletRequest request=getRequest();
String token=request.getAttribute(Constants.USER_TOKEN).toString();
tokenManager.loginOff(token);
}
}
上面是对用户信息基本操作
对用户进行控制,部分接口可以不登陆访问
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthIgnore { }
拦截器:
@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
AuthIgnore annotation;
if(handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);
}else{
return true;
} //如果有@AuthIgnore注解,则不验证token
if(annotation != null){
return true;
} //获取用户凭证
String token = request.getHeader(Constants.USER_TOKEN);
if(StringUtils.isBlank(token)){
token = request.getParameter(Constants.USER_TOKEN);
}
if(StringUtils.isBlank(token)){
Object obj = request.getAttribute(Constants.USER_TOKEN);
if(null!=obj){
token=obj.toString();
}
} //token凭证为空
if(StringUtils.isBlank(token)){
throw new AuthException(Constants.USER_TOKEN + "不能为空", HttpStatus.UNAUTHORIZED.value());
} return true;
}
}
如果token参数必须放在请求体中,直接读取请求体会报错,requestbody miss
解决方法:https://www.cnblogs.com/hongdada/p/9171739.html
这里的注解只是标注那些不需要登陆的接口
上面相关redis操作在上面也写过,请看前面文章。