Spring下token過期時(shí)間分平臺(tái)(web和app)設(shè)置方法
前言
本文介紹了Spring下的登錄和鑒權(quán)機(jī)制的主要方法以及 token認(rèn)證的主要流程,并介紹在spring中web端和APP端設(shè)置不同token過期時(shí)間的實(shí)現(xiàn)方法。主要基于SpringBoot+springSecurity+JWT框架實(shí)現(xiàn)。
一、應(yīng)用場景
同一系統(tǒng)的跨平臺(tái)操作,基于用戶習(xí)慣,web端和app端用戶使用時(shí)間長短常常不同,統(tǒng)一過長時(shí)間容易造成服務(wù)器資源浪費(fèi),統(tǒng)一過短使得用戶未操作完就登錄過期。因此,為更便于用戶使用,分平臺(tái)設(shè)置token過期時(shí)間能提升用戶體驗(yàn)。
二、登錄方法和token鑒權(quán)
要分平臺(tái)設(shè)置token過期時(shí)間,首先要了解SpringSecurity登錄流程的主要方法和token生成。
1、登錄流程
登錄-->校驗(yàn)用戶名、密碼、驗(yàn)證碼-->redis存儲(chǔ)登錄用戶信息-->生成token(JWT)-->返回token
// 僅展示關(guān)鍵語句
@PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { AjaxResult ajax = AjaxResult.success(); // 生成令牌 String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid(),loginBody.getClientPubKey(), loginBody.getPlatForm()); ajax.put(Constants.TOKEN, token); return ajax; }
public String login(String username, String aes_password, String code, String uuid, String clientPubKey, String platForm) { // 驗(yàn)證用戶名密碼 authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); LoginUser loginUser = (LoginUser) authentication.getPrincipal(); // 生成token loginUser.setPlatForm(platForm); return tokenService.createToken(loginUser); }
2、JWT
JWT是一種基于 Token 的認(rèn)證授權(quán)機(jī)制, 可用于創(chuàng)建token。
Token = Head+info+sign
Head: 編碼方式
Info:用戶信息,包括用戶名等自定義信息
Sign:簽名
如下所示:
Map<String, Object> claims = new HashMap<>(); claims.put(Constants.LOGIN_USER_KEY, token); claims.put(Constants.JWT_USERID, loginUser.getUserId()); claims.put(Constants.JWT_USERNAME, loginUser.getUsername()); private String createToken(Map<String, Object> claims) { String token = Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.HS512, secret).compact(); return token; }
3、Token鑒權(quán)
登錄后返回的token存于前端緩存,每次請(qǐng)求時(shí)放于請(qǐng)求頭,經(jīng)過攔截器時(shí)解析token,并verifyToken方法校驗(yàn)token是否有效或過期,同時(shí)redreshToken延長過期時(shí)間(本次為活躍)。
// 校驗(yàn)
public void verifyToken(LoginUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); if(loginUser.getPlatForm().equals("pc")){ if (expireTime - currentTime <= MILLIS_MINUTE_TEN_PC) { refreshToken(loginUser); } }else if(loginUser.getPlatForm().equals("app")) { if (expireTime - currentTime <= MILLIS_MINUTE_TEN_APP) { refreshToken(loginUser); } } }
// 更新過期時(shí)間
public void refreshToken(LoginUser loginUser) { if(loginUser.getPlatForm().equals("pc")){ expireTime = pcExpireTime; }else if(loginUser.getPlatForm().equals("app")){ expireTime = appExpireTime; } loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); // 根據(jù)uuid將loginUser緩存 String userKey = getTokenKey(loginUser.getToken()); redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); }
三、實(shí)現(xiàn)方法
1、配置文件
Pc端過期時(shí)間59min,app端3天
# token配置 token: # 令牌自定義標(biāo)識(shí) header: Authorization # 令牌密鑰 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默認(rèn)59分鐘; APP端3天) expireTime: defaultExpireTime: 59 pcExpireTime: 59 appExpireTime: 4320
2、登錄信息實(shí)體類
增加平臺(tái)信息
src/main/java/com/common/core/domain/model/LoginBody.java
src/main/java/com/common/core/domain/model/LoginUser.java
public class LoginBody { // ****其他省略 /** * 登錄平臺(tái): 手機(jī)端='app',PC端='pc' */ private String platForm; public String getPlatForm() { return platForm; } public void setPlatForm(String platForm) { this.platForm = platForm; } }
3、登錄方法
(1)login的controller層方法
生成token的方法參數(shù)加上平臺(tái)信息
src/main/java/com/web/controller/system/SysLoginController.java
@PostMapping("/login") public AjaxResult login(@RequestBody LoginBody loginBody) { AjaxResult ajax = AjaxResult.success(); // 生成令牌 String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid(),loginBody.getClientPubKey(), loginBody.getPlatForm()); ajax.put(Constants.TOKEN, token); return ajax; }
(2)登錄信息檢驗(yàn)及token生成
src/main/java/com/inspur/framework/web/service/SysLoginService.java
// 基于SpringSecurity的驗(yàn)證方法,修改返回的登錄用戶信息,可以在返回后再人工設(shè)置。
public String login(String username, String aes_password, String code, String uuid, String clientPubKey, String platForm) { // 僅僅展示重要關(guān)鍵語句 // 驗(yàn)證用戶名密碼 authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); // 返回登錄信息 LoginUser loginUser = (LoginUser) authentication.getPrincipal(); // 生成token loginUser.setPlatForm(platForm); return tokenService.createToken(loginUser); }
private String createToken(Map<String, Object> claims) { String token = Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.HS512, secret).compact(); return token; }
(3)Token驗(yàn)證鑒權(quán)及更新
src/main/java/com/inspur/common/service/TokenService.java
// 用戶每次請(qǐng)求將token信息存放于請(qǐng)求頭,經(jīng)過攔截器攔截。
@Component public class TokenService { // 令牌有效期(默認(rèn)30分鐘) @Value("${token.expireTime.defaultExpireTime}") private int expireTime; @Value("${token.expireTime.pcExpireTime}") private int pcExpireTime; @Value("${token.expireTime.appExpireTime}") private int appExpireTime; //pc端-距離20分鐘時(shí)刷新token過期時(shí)間 private static final Long MILLIS_MINUTE_TEN_PC = 20 * 60 * 1000L; //app端-距離1天時(shí)刷新token過期時(shí)間 private static final Long MILLIS_MINUTE_TEN_APP = 24 * 60 * 60 * 1000L; public void verifyToken(LoginUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); if(loginUser.getPlatForm().equals("pc")){ if (expireTime - currentTime <= MILLIS_MINUTE_TEN_PC) { refreshToken(loginUser); } }else if(loginUser.getPlatForm().equals("app")) { if (expireTime - currentTime <= MILLIS_MINUTE_TEN_APP) { refreshToken(loginUser); } } }
public void refreshToken(LoginUser loginUser) { if(loginUser.getPlatForm().equals("pc")){ expireTime = pcExpireTime; }else if(loginUser.getPlatForm().equals("app")){ expireTime = appExpireTime; } loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); // 根據(jù)uuid將loginUser緩存 String userKey = getTokenKey(loginUser.getToken()); redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); } }
4、前端傳遞平臺(tái)信息
(1)web端(基于Vue)
登錄傳遞平臺(tái)信息:platForm=‘pc’
src/store/modules/user.js
// 登錄 Login({commit}, userInfo) { const username = userInfo.username.trim() const password = userInfo.password const code = userInfo.code const uuid = userInfo.uuid const platForm = 'pc' return new Promise((resolve, reject) => { getPublicKey(username).then(res => { if (res.code === 200) { let result = encryptData(res.data, password); let aes_password = result.encryptedData; login(username, aes_password, code, uuid,result.clientKey,platForm).then(res => { setToken(res.token) commit('SET_TOKEN', res.token) resolve() }).catch(error => { reject(error) }) } }) }) },
src/api/login.js
export function login(username, password, code, uuid,clientPubKey) { const platForm = 'pc' const data = { username, password, code, uuid, clientPubKey, platForm } return request({ url: '/login', method: 'post', data: data }) }
(2)app端(基于uniapp)
api/login.js
// 登錄方法 export function login(username, password, code, uuid) { let platForm = 'app' const data = { username, password, code, uuid, platForm } return request({ 'url': '/appLogin', headers: { isToken: false }, 'method': 'post', 'data': data }) }
總結(jié)
到此這篇關(guān)于Spring下token過期時(shí)間分平臺(tái)(web和app)設(shè)置的文章就介紹到這了,更多相關(guān)token過期時(shí)間分平臺(tái)設(shè)置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別
這篇文章主要介紹了關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12利用Java搭建個(gè)簡單的Netty通信實(shí)例教程
這篇文章主要給大家介紹了關(guān)于如何利用Java搭建個(gè)簡單的Netty通信,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Java ScheduledExecutorService的具體使用
ScheduledExecutorService有線程池的特性,也可以實(shí)現(xiàn)任務(wù)循環(huán)執(zhí)行,本文主要介紹了Java ScheduledExecutorService的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-05-05SpringMVC中的SimpleUrlHandlerMapping用法詳解
這篇文章主要介紹了SpringMVC中的SimpleUrlHandlerMapping用法詳解,SimpleUrlHandlerMapping是Spring MVC中適用性最強(qiáng)的Handler Mapping類,允許明確指定URL模式和Handler的映射關(guān)系,有兩種方式聲明SimpleUrlHandlerMapping,需要的朋友可以參考下2023-10-10關(guān)于SpringBoot中的XA事務(wù)詳解
這篇文章主要介紹了關(guān)于SpringBoot中的XA事務(wù)詳解,事務(wù)管理可以確保數(shù)據(jù)的一致性和完整性,同時(shí)也可以避免數(shù)據(jù)丟失和沖突等問題。在分布式環(huán)境中,XA?事務(wù)是一種常用的事務(wù)管理方式,需要的朋友可以參考下2023-07-07