<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()即可;