采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新
生活随笔
收集整理的這篇文章主要介紹了
采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在寫token登錄的時候,發現cookie中的token到時自動失效,如果此時有人正在操作,非常影響體驗,于是增加了一個token快失效時刷新token的功能。下面代碼重點就在TokenTool類中的時間判斷
1.先寫一個tokenTime的工具類
public class TokenTime {/*1小時以內,token有效1-2小時之內,token進行刷新2小時之后,token失效*///cookie和redis中token超過一小時刷新public static final int TokenOutTime_hour=1;//cookie瀏覽器保存token有效期設為2小時public static final int cookie_time=60 * 60 * 2;//redis保存token有效期設為2小時public static final int redis_time=60 * 60 * 2;}2.再寫一個TokenTool的工具類
public class TokenTool {//生成Tokenpublic String CreateToken(){LocalDateTime now=LocalDateTime.now();//年月日時分秒毫秒Date date =new Date();String uuid = UUID.randomUUID().toString();String token=uuid+date.getTime();return token;}//判斷token時間戳是否需要刷新public boolean tokenOutTime(String OldToken) throws ParseException {//年月日時分秒毫秒Date date =new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");int Oldmax=OldToken.length();long Newtime=date.getTime();long Oldtime = Long.parseLong(OldToken.substring(36, Oldmax));/*給cookie中的時間加上一小時,1小時以內,token有效1-2小時之內,token進行刷新2小時之后,token失效*/Long OldLoseTime= addDate(Oldtime, TokenTime.TokenOutTime_hour);Date NewDate = new Date(Newtime);Date oldDate = new Date(OldLoseTime);String st= simpleDateFormat.format(oldDate);String en= simpleDateFormat.format(NewDate);Date oldTokenTime=simpleDateFormat.parse(st);Date newTokenTime=simpleDateFormat.parse(en);if (oldTokenTime.before(newTokenTime)){System.out.println("token需要刷新");return true;}else{System.out.println("token不需要刷新");return false;}}//給時間戳增加時間public static Long addDate(long time,long hour) throws ParseException {hour = hour*1*60*60*1000; // 要加上的天數轉換成毫秒數time+=hour; // 相加得到新的毫秒數return time; // 將毫秒數轉換成日期} }?
3.然后寫一個登錄接口,代碼已經假設你從數據庫拿到了用戶信息保存在變量userinfo中,將token返回給瀏覽器保存,并將token和userinfo保存在redis中。
@Resourceprivate RedisTemplate redisTemplate;@RequestMapping("/login")public R token(HttpServletRequest request, HttpServletResponse response) {//假設此時已經從數據庫獲取到用戶信息在userinfoTokenTool token =new TokenTool();String cretoken=token.CreateToken();//生成tokenCookie cookie=new Cookie("tokenUser",cretoken);cookie.setMaxAge(TokenTime.cookie_time);//有效期設為2小時//設置路徑cookie.setPath("/");//響應回游覽器response.addCookie(cookie);RedisCache redis=new RedisCache(redisTemplate);redis.set(cretoken,userinfo,TokenTime.redis_time);//有效期設為2小時return R.ok(userinfo,"登錄成功");}4.新建一個類型,這個是全局線程。當用戶信息經過token驗證從redis拿出來之后要保存在這個里面,想用的時候從這個里面拿取就行了。
public class UserThreadLocal {private static ThreadLocal<User> userThread =new ThreadLocal<User>();public static void set(User user){userThread.set(user);}public static User get(){return userThread.get();}//防止內存泄漏public static void remove(){userThread.remove();} }5.新建一個攔截器,業務邏輯是 獲取瀏覽器token,再從redis獲取userinfo,將userinfo保存在UserThreadLocal線程中。
@Configuration public class LoginInterceptor implements HandlerInterceptor {@Resourceprivate RedisTemplate redisTemplate;@Autowiredprivate static ObjectMapper objectMapper = new ObjectMapper();//在執行COntroller方法之前執行/*** boolean 表示是否放行* true:放行 用戶可以跳轉頁面* false:攔截 之后給定重定向路徑** 業務邏輯:* 1.判斷用戶客戶端是否有Cookie/token數據* 如果用戶沒有token則重定向到用戶登陸頁面* 2.如果用戶token中有數據,則從redis緩存中獲取數據* 如果redis中數據為null,則重定向到用戶登陸頁面* 3.如果reids中有數據,則放行請求.*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String token = "";//獲取Cookie數據Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if("tokenUser".equals(cookie.getName())){token = cookie.getValue();break;}}//判斷Cookie是否為nullif(!StringUtils.isEmpty(token)){//檢測緩存中是否有該數據RedisCache redis=new RedisCache(redisTemplate);Object userinfo = redis.get(token);TokenTool cretoken =new TokenTool();if(cretoken.tokenOutTime(token)){String cookiesAndRedisToken=cretoken.CreateToken();Cookie cookie=new Cookie("tokenUser",cookiesAndRedisToken);cookie.setMaxAge(TokenTime.cookie_time);//有效期設為2小時//設置路徑cookie.setPath("/");//響應回游覽器response.addCookie(cookie);redis.set(cookiesAndRedisToken,userinfo,TokenTime.redis_time);//有效期設為2小時if(!StringUtils.isEmpty(userinfo)){//將userJSON轉化為User對象User user= (User) userinfo;UserThreadLocal.set(user);//用戶已經登陸 放行請求return true;}}else{if(!StringUtils.isEmpty(userinfo)){//將userJSON轉化為User對象User user= (User) userinfo;UserThreadLocal.set(user);//用戶已經登陸 放行請求return true;}}}//表示用戶沒有登陸response.sendRedirect("/login.html");return false;}//執行完業務邏輯后攔截@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// TODO Auto-generated method stub}//返回頁面之前攔截@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {//將ThreadLocal數據清空UserThreadLocal.remove();}}6.新建一個攔截器配置類,設置要訪問攔截器的路徑,開放登錄接口和靜態資源接口,其他都配置成要訪問攔截器
@Configuration public class InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry){//添加對用戶未登錄的攔截器,并添加排除項registry.addInterceptor(loginInterceptor).addPathPatterns("/**")//攔截所有.excludePathPatterns("/js/**","/dist/images/**")//排除樣式、腳本、圖片等資源文件.excludePathPatterns("/login")//排除登錄.excludePathPatterns("/","/index");} }7.獲取用戶信息
@RequestMapping("/getuserinfo")public R getuserinfo() {User user = UserThreadLocal.get();System.out.println(user);return R.ok(user,"獲取用戶信息成功");}?
總結
以上是生活随笔為你收集整理的采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度app如何设置青少年模式(百度产品大
- 下一篇: Java获取linux服务器cpu、内存