<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>3.2.0</version>
</dependency>
package com.chitic.common.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chitic.bank.model.Userinfo;
import com.chitic.bank.web.exception.UnauthorizeException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author GX
* @version 1.0*/
public class JWTToken {
/**
* 生成token
* @return
* @throws Exception
*/
public static String createToken(Userinfo user) throws Exception{
// 签发时间
Date iatDate=new Date();
// 过期时间-outTime分钟过期
Calendar nowTime=Calendar.getInstance();
nowTime.add(Calendar.MINUTE, ValuesUtil.OutTime);
Date expiresDate=nowTime.getTime();
Map<String,Object> map=new HashMap<String,Object>();
map.put(ParamsUtil.Alg_Key, ValuesUtil.Alg_RS256);
map.put(ParamsUtil.Typ_Key, ValuesUtil.Typ_JWT);
String token="";
token=JWT.create()
.withHeader(map)
.withClaim(ParamsUtil.User_Key, user.getUsername())
.withClaim(ParamsUtil.Id_Key, user.getId())
.withClaim(ParamsUtil.Role_Key, user.getRole())
.withClaim(ParamsUtil.Rights_Key,user.getRights())
.withExpiresAt(expiresDate)//设置过期时间-过期时间要大于签发时间
.withIssuedAt(iatDate)//设置签发时间
.sign(Algorithm.HMAC256(ValuesUtil.SECRET));//加密
return token;
}
/**
* 解密token
* @param token
* @return
* @throws Exception
*/
public static Map<String,Claim> verifyToken(String token) throws Exception {
JWTVerifier verifier=JWT.require(Algorithm.HMAC256(ValuesUtil.SECRET)).build();
DecodedJWT jwt=null;
try {
jwt=verifier.verify(token);
} catch (Exception e) {
// throw new RuntimeException("登录已失效,请重新登录");
throw new UnauthorizeException(1006, "登录已失效,请重新登录");
}
return jwt.getClaims();
}
}
private void doUser(ProceedingJoinPoint pjd) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//使用MDC,需要引入log4j
MDC.clear();
String token=request.getHeader(ParamsUtil.Token_Key);
MethodSignature methodSignature = (MethodSignature) pjd.getSignature();
Method method = methodSignature.getMethod();
boolean noAuthorize = method.isAnnotationPresent(NoAuth.class);
if (!noAuthorize) {
Map<String, Claim> claim=JWTToken.verifyToken(token);
String username=claim.get(ParamsUtil.User_Key).asString();
int user_id=claim.get(ParamsUtil.Id_Key).asInt();
int role=claim.get(ParamsUtil.Role_Key).asInt();
Integer rights=null;
if(!StringUtil.checkObj(claim.get(ParamsUtil.Rights_Key))){
rights=claim.get(ParamsUtil.Rights_Key).asInt();
}
if (StringUtil.isBlank(username) || StringUtil.checkObj(user_id)
|| StringUtil.checkObj(role)) {
throw ChiticException.of(ChiticResponseCode.ACCESS_DENY);
}
HashMap<String,Object> params=new HashMap<String,Object>();
params.put(ParamsUtil.User_Sn_Key, username);
params.put(ParamsUtil.User_Id_Key, user_id);
Userinfo user=userService.findUserBySNId(params);
if (null == user) {
throw ChiticException.of(ChiticResponseCode.userLoginNotFound);
}else{
if(StringUtil.checkObj(user.getRole())||user.getRole()!=role){
throw ChiticException.of(ChiticResponseCode.Rights_Change);
}
int user_rights=user.getRights()==null||user.getRights().toString().equals("")?null:user.getRights();
if(user_rights!=rights){
throw ChiticException.of(ChiticResponseCode.Rights_Change);
}
}
UserThreadLocal.set(UserCacheInfo.builder()
.userId(user.getId())
.username(user.getUsername())
.role(user.getRole())
.ismanage(user.getRights())
.build());
MDC.put(ParamsUtil.User_Sn_Key, username);
MDC.put(ParamsUtil.User_Id_Key, String.valueOf(user_id));
MDC.put(ParamsUtil.Role_Key, String.valueOf(user.getRole()));
if (method.isAnnotationPresent(RoleAdmin.class) && !ValuesUtil.isAdminRole()) {
throw ChiticException.of(ChiticResponseCode.ACCESS_DENY);
}
}
}
前端存到localStorage,只支持写入字符串
if(!window.localStorage){
alert("浏览器支持localstorage");
return false;
}else{
var storage=window.localStorage;
//写入a字段
storage["a"]=1;
//写入b字段
storage.a=1;
//写入c字段
storage.setItem("c",3);
console.log(typeof storage["a"]);
console.log(typeof storage["b"]);
console.log(typeof storage["c"]);
}
使用sessionStorage也可以
并发ThreadLocal的使用
ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
使用
//创建ThreadLocal,里面存登录的用户信息
private static final ThreadLocal<UserCacheInfo> local = new ThreadLocal<>();
//最常用的三个方法
//local.set();
//local.get();
//local.remove();
try {
//用户登录成功之后,将其用户信息放到local中
local.set(user);
doUser(pjp);//用户信息校验
} catch (Exception e) {
log.error("请求出错,错误信息: {}",e);
} catch (Throwable e) {
log.error("请求出错,错误信息: {}",e);
} finally {
//注意要关闭
if (null != UserThreadLocal.get()) {
UserThreadLocal.remove();
}
}
//使用的话调用local.get()即可;