Token机制改造过程中踩坑记录
上个月为了修改系统的认证方式为Token机制,编码两天,修BUG修了一整周,天天加班到深夜,踩坑无数,终于爬上来了,现记录如下。
问题背景
- 系统原有登录认证机制为手机号+验证码登录并保存Cookie,由前端调用CheckLogin接口判断登录信息是否还存在,后端通过Cookie里的userId来关联用户信息;
- 此种认证方案在我接手后就提出优化意见,不过由于任务繁多,直到前些日子才抽出时间修改;
- 和前端同学一起讨论确定认证方式为Token机制,具体见博文微信公众号用户认证机制升级方案;
具体实现
用户认证登录实现
/** * 用户认证登录接口 * @param auth * @return */ @RequestMapping(method = RequestMethod.POST) public BaseResult<UserToken> auth(@RequestBody AuthVO auth, @RequestHeader("timestamp") Long timestamp) throws Exception { //省略前置校验等代码 //生成UserToken和SecretKey String token = MD5.getInstance().getMD5String(UUID.randomUUID().toString()); while (redisTemplate.opsForValue().get(USER_TOKEN_REDIS_PRE+token) != null){ token = MD5.getInstance().getMD5String(UUID.randomUUID().toString()); } String secretKey = MD5.getInstance().getMD5String(UUID.randomUUID().toString()); Long expire = calendar.getTimeInMillis(); UserToken userToken = new UserToken(token,secretKey,expire); //更新用户的SecretKey member.setSecretKey(secretKey); memberService.updateMemberById(member); //将Token & userId存入Redis redisTemplate.opsForValue().set(USER_TOKEN_REDIS_PRE+token, String.valueOf(member.getId()), 30, TimeUnit.DAYS); return BaseResultUtils.ok(userToken); }
鉴权注解
/** * 鉴权注解,在Controller的方法上添加该注解表明此方法需要进行登录信息鉴权 * 未登录返回 401 错误 - 未授权 (Unauthorized) * User: za-panyong * Date: 2018/5/9 * Time: 15:27 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Authorization { }
RequestBody过滤器
public class RequestFilter implements Filter { //线程缓存,保存RequestBody public static ThreadLocal<MyRequestBodyReaderWrapper> REQUEST_WRAPPER = new ThreadLocal<>(); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest servletRequest = (HttpServletRequest) request; //如果是GET请求或者请求类型不是application/json,则不需要获取RequestBody if (StringUtils.isEmpty(servletRequest.getMethod()) || "GET".equalsIgnoreCase(servletRequest.getMethod())