代碼:html
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); }
具體實現:redis
@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參數dom
@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); } }
上面是對用戶信息基本操做ide
對用戶進行控制,部分接口能夠不登錄訪問ui
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuthIgnore { }
攔截器:spa
@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 misscode
解決方法:http://www.javashuo.com/article/p-tflplwns-bo.htmlorm
這裏的註解只是標註那些不須要登錄的接口htm
上面相關redis操做在上面也寫過,請看前面文章。blog