1登录验证,验证成功制作通过JWT制作token,返回token
@PostMapping("login") @ResponseBody public String login(UserInfo userInfo, HttpServletRequest request){ UserInfo userInfoExist= userService.login(userInfo); //1 if(userInfoExist!=null){ //制作token Map<String, Object> map = new HashMap<>(); map.put("userId",userInfoExist.getId()); map.put("nickName",userInfoExist.getNickName()); System.out.println(request.getRemoteAddr()); // // 如果有 反向代理的话 ,要在反向代理中进行配置 把用户真实ip传递过来 String ipAddr = request.getHeader("X-forwarded-for"); String token = JwtUtil.encode(jwtKey, map, ipAddr); return token; }
2前端页面逻辑href=orginUrl+"?token="+token,去认证中心认证,url中携带token。
拦截器逻辑进行拦截,拿到url中的newToken,并写到cookie中,此处可以设置cookie的过期时间定为7天。将userMap中的用户名信息取出来。通过@loginRequire注解决定是否对该url进行拦截,需要拦截的话,如果token不为空,通过HttpClientUtil.doGet(VERIFY_URL + "?token=" + token + "¤tIP=" + currentIP);方法进行验证,如果返回success,则验证成功,并将request的userid设置。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 检查token token可能存在 1 url参数 newToken 2 从cookie中获得 token String token=null; //1 newToken的情况 token = request.getParameter("newToken"); if(token !=null){ //把token保存到cookie中 CookieUtil.setCookie(request,response,"token",token, WebConst.cookieMaxAge,false); }else{ //从cookie中取值 token token = CookieUtil.getCookieValue(request, "token", false); } //如果token 从token中把用户信息取出来 Map userMap=new HashMap(); if(token!=null){ userMap = getUserMapfromToken(token); String nickName = (String)userMap.get("nickName"); request.setAttribute("nickName",nickName); } //判断是否该请求需要用户登录 //取到请求的方法上的注解 LoginRequire HandlerMethod handlerMethod = (HandlerMethod) handler; LoginRequire loginRequire = handlerMethod.getMethodAnnotation(LoginRequire.class); if(loginRequire!=null){ //需要认证 if(token!=null){ // 要把token 发给认证中心进行 认证 String currentIP = request.getHeader("X-forwarded-for"); String result = HttpClientUtil.doGet(VERIFY_URL + "?token=" + token + "¤tIP=" + currentIP); if("success".equals(result)){ //认证成功 String userId =(String) userMap.get("userId"); request.setAttribute("userId",userId); return true; }else if(!loginRequire.autoRedirect()) { //认证失败但是 运行不跳转 return true; }else { //认证失败 强行跳转 redirect( request, response); return false; } }else { // 强行跳转 // 进行重定向 passport 让用户登录 if(!loginRequire.autoRedirect()) { //认证失败但是 运行不跳转 return true; }else{ redirect( request, response); return false; } } } return true; }
3其他有@loginRequire请求时,通过拦截器进入认证中心,通过新老token,调用HttpClientUtil.doGet(VERIFY_URL + "?token=" + token + "¤tIP=" + currentIP);进行验证。验证时通过解析token拿到userID,再调用verfify方法验证。verfify方法通过 jedis.exists(userKey),看缓存中是否存在userKey。如果存在再 jedis.expire(userKey,userKey_timeOut)延长缓存过期时间,达到token的时效性。
//http://passport.gmall.com/verify?token=xxxx¤tIP=xxxx @GetMapping("verify") @ResponseBody public String verify(@RequestParam("token") String token, @RequestParam("currentIP") String currentIp){ //1 验证token Map<String, Object> userMap = JwtUtil.decode(token, jwtKey, currentIp); //2 验证缓存 if(userMap!=null){//可能是伪造了一个usermap String userId = (String)userMap.get("userId"); Boolean isLogin= userService.verify(userId);//看看是否有效的userid if(isLogin){ return "success"; } } return "fail"; }