北京市建设资格注册中心网站,大连网站建设设计,小程序代理是做什么的,pis粉丝做的网站token分平台设置方法 本文介绍了Spring下的登录和鉴权机制的主要方法以及 token认证的主要流程#xff0c;并介绍在spring中web端和APP端设置不同token过期时间的实现方法。主要基于SpringBootspringSecurityJWT框架实现。
一、应用场景 同一系统的跨平台操作#xff0c;基于…token分平台设置方法 本文介绍了Spring下的登录和鉴权机制的主要方法以及 token认证的主要流程并介绍在spring中web端和APP端设置不同token过期时间的实现方法。主要基于SpringBootspringSecurityJWT框架实现。
一、应用场景 同一系统的跨平台操作基于用户习惯web端和app端用户使用时间长短常常不同统一过长时间容易造成服务器资源浪费统一过短使得用户未操作完就登录过期。因此为更便于用户使用分平台设置token过期时间能提升用户体验。
二、登录方法和token鉴权
要分平台设置token过期时间首先要了解SpringSecurity登录流程的主要方法和token生成。
1、登录流程
登录--校验用户名、密码、验证码--redis存储登录用户信息--生成token(JWT)--返回token
// 仅展示关键语句
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) {// 验证用户名密码authentication authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));LoginUser loginUser (LoginUser) authentication.getPrincipal();// 生成token
loginUser.setPlatForm(platForm);
return tokenService.createToken(loginUser);} 2、JWT
JWT是一种基于 Token 的认证授权机制, 可用于创建token。
Token Headinfosign
Head 编码方式
Info用户信息包括用户名等自定义信息
Sign签名
如下所示
MapString, 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(MapString, Object claims)
{String token Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();return token;
} 3、Token鉴权 登录后返回的token存于前端缓存每次请求时放于请求头经过拦截器时解析token并verifyToken方法校验token是否有效或过期同时redreshToken延长过期时间(本次为活跃)。
// 校验
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);// 根据uuid将loginUser缓存String userKey getTokenKey(loginUser.getToken());redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
三、实现方法
1、配置文件
Pc端过期时间59minapp端3天
# token配置
token:# 令牌自定义标识header: Authorization# 令牌密钥secret: abcdefghijklmnopqrstuvwxyz# 令牌有效期默认59分钟; APP端3天expireTime:defaultExpireTime: 59pcExpireTime: 59appExpireTime: 4320
2、登录信息实体类
增加平台信息
src/main/java/com/common/core/domain/model/LoginBody.java
src/main/java/com/common/core/domain/model/LoginUser.java
public class LoginBody {// ****其他省略/*** 登录平台: 手机端app,PC端pc*/
private String platForm;
public String getPlatForm() {return platForm;
}
public void setPlatForm(String platForm) {this.platForm platForm;
}} 3、登录方法
1login的controller层方法
生成token的方法参数加上平台信息
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) 登录信息检验及token生成
src/main/java/com/inspur/framework/web/service/SysLoginService.java
// 基于SpringSecurity的验证方法修改返回的登录用户信息可以在返回后再人工设置。
public String login(String username, String aes_password, String code, String uuid, String clientPubKey, String platForm) {// 仅仅展示重要关键语句// 验证用户名密码authentication authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));// 返回登录信息LoginUser loginUser (LoginUser) authentication.getPrincipal();// 生成token
loginUser.setPlatForm(platForm);
return tokenService.createToken(loginUser);} private String createToken(MapString, Object claims)
{String token Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();return token;
} 3Token验证鉴权及更新
src/main/java/com/inspur/common/service/TokenService.java
// 用户每次请求将token信息存放于请求头经过拦截器拦截。
Component
public class TokenService
{// 令牌有效期默认30分钟Value(${token.expireTime.defaultExpireTime})
private int expireTime;Value(${token.expireTime.pcExpireTime})
private int pcExpireTime;
Value(${token.expireTime.appExpireTime})
private int appExpireTime;//pc端-距离20分钟时刷新token过期时间
private static final Long MILLIS_MINUTE_TEN_PC 20 * 60 * 1000L;
//app端-距离1天时刷新token过期时间
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);// 根据uuid将loginUser缓存String userKey getTokenKey(loginUser.getToken());redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}} 4、前端传递平台信息
1web端基于Vue
登录传递平台信息platForm‘pc’
src/store/modules/user.js
// 登录
Login({commit}, userInfo) {const username userInfo.username.trim()const password userInfo.passwordconst code userInfo.codeconst uuid userInfo.uuidconst platForm pcreturn 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 pcconst 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 appconst data {username,password,code,uuid,platForm}return request({url: /appLogin,headers: {isToken: false},method: post,data: data})
}