日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新

發(fā)布時(shí)間:2023/12/31 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在寫token登錄的時(shí)候,發(fā)現(xiàn)cookie中的token到時(shí)自動(dòng)失效,如果此時(shí)有人正在操作,非常影響體驗(yàn),于是增加了一個(gè)token快失效時(shí)刷新token的功能。下面代碼重點(diǎn)就在TokenTool類中的時(shí)間判斷

1.先寫一個(gè)tokenTime的工具類

public class TokenTime {/*1小時(shí)以內(nèi),token有效1-2小時(shí)之內(nèi),token進(jìn)行刷新2小時(shí)之后,token失效*///cookie和redis中token超過一小時(shí)刷新public static final int TokenOutTime_hour=1;//cookie瀏覽器保存token有效期設(shè)為2小時(shí)public static final int cookie_time=60 * 60 * 2;//redis保存token有效期設(shè)為2小時(shí)public static final int redis_time=60 * 60 * 2;}

2.再寫一個(gè)TokenTool的工具類

public class TokenTool {//生成Tokenpublic String CreateToken(){LocalDateTime now=LocalDateTime.now();//年月日時(shí)分秒毫秒Date date =new Date();String uuid = UUID.randomUUID().toString();String token=uuid+date.getTime();return token;}//判斷token時(shí)間戳是否需要刷新public boolean tokenOutTime(String OldToken) throws ParseException {//年月日時(shí)分秒毫秒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中的時(shí)間加上一小時(shí),1小時(shí)以內(nèi),token有效1-2小時(shí)之內(nèi),token進(jìn)行刷新2小時(shí)之后,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;}}//給時(shí)間戳增加時(shí)間public static Long addDate(long time,long hour) throws ParseException {hour = hour*1*60*60*1000; // 要加上的天數(shù)轉(zhuǎn)換成毫秒數(shù)time+=hour; // 相加得到新的毫秒數(shù)return time; // 將毫秒數(shù)轉(zhuǎn)換成日期} }

?

3.然后寫一個(gè)登錄接口,代碼已經(jīng)假設(shè)你從數(shù)據(jù)庫(kù)拿到了用戶信息保存在變量userinfo中,將token返回給瀏覽器保存,并將token和userinfo保存在redis中。

@Resourceprivate RedisTemplate redisTemplate;@RequestMapping("/login")public R token(HttpServletRequest request, HttpServletResponse response) {//假設(shè)此時(shí)已經(jīng)從數(shù)據(jù)庫(kù)獲取到用戶信息在userinfoTokenTool token =new TokenTool();String cretoken=token.CreateToken();//生成tokenCookie cookie=new Cookie("tokenUser",cretoken);cookie.setMaxAge(TokenTime.cookie_time);//有效期設(shè)為2小時(shí)//設(shè)置路徑cookie.setPath("/");//響應(yīng)回游覽器response.addCookie(cookie);RedisCache redis=new RedisCache(redisTemplate);redis.set(cretoken,userinfo,TokenTime.redis_time);//有效期設(shè)為2小時(shí)return R.ok(userinfo,"登錄成功");}

4.新建一個(gè)類型,這個(gè)是全局線程。當(dāng)用戶信息經(jīng)過token驗(yàn)證從redis拿出來(lái)之后要保存在這個(gè)里面,想用的時(shí)候從這個(gè)里面拿取就行了。

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();}//防止內(nèi)存泄漏public static void remove(){userThread.remove();} }

5.新建一個(gè)攔截器,業(yè)務(wù)邏輯是 獲取瀏覽器token,再?gòu)膔edis獲取userinfo,將userinfo保存在UserThreadLocal線程中。

@Configuration public class LoginInterceptor implements HandlerInterceptor {@Resourceprivate RedisTemplate redisTemplate;@Autowiredprivate static ObjectMapper objectMapper = new ObjectMapper();//在執(zhí)行COntroller方法之前執(zhí)行/*** boolean 表示是否放行* true:放行 用戶可以跳轉(zhuǎn)頁(yè)面* false:攔截 之后給定重定向路徑** 業(yè)務(wù)邏輯:* 1.判斷用戶客戶端是否有Cookie/token數(shù)據(jù)* 如果用戶沒有token則重定向到用戶登陸頁(yè)面* 2.如果用戶token中有數(shù)據(jù),則從redis緩存中獲取數(shù)據(jù)* 如果redis中數(shù)據(jù)為null,則重定向到用戶登陸頁(yè)面* 3.如果reids中有數(shù)據(jù),則放行請(qǐng)求.*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String token = "";//獲取Cookie數(shù)據(jù)Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if("tokenUser".equals(cookie.getName())){token = cookie.getValue();break;}}//判斷Cookie是否為nullif(!StringUtils.isEmpty(token)){//檢測(cè)緩存中是否有該數(shù)據(jù)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);//有效期設(shè)為2小時(shí)//設(shè)置路徑cookie.setPath("/");//響應(yīng)回游覽器response.addCookie(cookie);redis.set(cookiesAndRedisToken,userinfo,TokenTime.redis_time);//有效期設(shè)為2小時(shí)if(!StringUtils.isEmpty(userinfo)){//將userJSON轉(zhuǎn)化為User對(duì)象User user= (User) userinfo;UserThreadLocal.set(user);//用戶已經(jīng)登陸 放行請(qǐng)求return true;}}else{if(!StringUtils.isEmpty(userinfo)){//將userJSON轉(zhuǎn)化為User對(duì)象User user= (User) userinfo;UserThreadLocal.set(user);//用戶已經(jīng)登陸 放行請(qǐng)求return true;}}}//表示用戶沒有登陸response.sendRedirect("/login.html");return false;}//執(zhí)行完業(yè)務(wù)邏輯后攔截@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// TODO Auto-generated method stub}//返回頁(yè)面之前攔截@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {//將ThreadLocal數(shù)據(jù)清空UserThreadLocal.remove();}}

6.新建一個(gè)攔截器配置類,設(shè)置要訪問攔截器的路徑,開放登錄接口和靜態(tài)資源接口,其他都配置成要訪問攔截器

@Configuration public class InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry){//添加對(duì)用戶未登錄的攔截器,并添加排除項(xiàng)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,"獲取用戶信息成功");}

?

總結(jié)

以上是生活随笔為你收集整理的采用redis+ThreadLocal获取全局的登录用户信息(二)增加token快失效时刷新的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。