JWT(JSON Web Token)認證小結
阿新 • • 發佈:2021-01-16
技術標籤:java後端# SpringBootjwtspring bootjava
jwt(JSON Web Token)
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC
algorithm) or a public/private key pair using RSA or ECDSA.
Jwt簡介
-
傳統認證通過session,但是前後端分離和分散式專案無法使用,
-
jwt向認證成功的使用者返回一個token,以後使用者每次請求都攜帶該token來實現認證
-
請求認證的token存放在客戶端
localStorage
中,請求時資料攜帶在header中,退出登入在loacalStorage中刪除該token即可
JWT結構
組成
jwt令牌由三部分組成
- 頭部(Header)
- 有效荷載(payload)
- 簽名(signature)
因此,JWT通常是xxxx.yyy.zzz
頭部(Header)
明文示例
{
"alg":"HS256",
"typ":"JWT"
}
alg
:加密演算法
typ
:型別
header部分會使用base64
編碼,注意,base64並不是加密的過程,可以解碼
Payload
{
"sub":"123465",
"name":"zhansan",
"admin":true
}
資料負載部分也會使用base64進行編碼,payLoad不要存放使用者敏感資訊
簽名(signature)
簽名使用編碼後的header和payload,以及一個金鑰,然後使用header中指定的簽名演算法進行簽名,簽名的作用是保證JWT沒有被篡改過
使用
pom依賴
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
生成token
//加密口令
String SECRET = "!Q$#&^&SCMd12";
Algorithm algorithm = Algorithm.HMAC256(SECRET);
//設施過期時間為10min
Calendar expireTime =Calendar.getInstance();
expireTime.add(Calendar.MINUTE,10);
Map<String,Object> map = new HashMap<>();
map.put("alg","HS256");
map.put("typ","JWT");
String tokenStr = JWT.create()
//header可以不用設定,一般用預設的就行
.withHeader(map)
.withClaim("uid", UUID.randomUUID().toString())
.withClaim("name", "console")
.withExpiresAt(expireTime.getTime())
.sign(algorithm);
}
解析token
//加密口令
String SECRET = "!Q$#&^&SCMd12";
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT verify = verifier.verify(token);
System.out.println(verify.getHeader());
System.out.println(verify.getPayload());
System.out.println(verify.getSignature());
System.out.println(verify.getClaim("uid").asString());
一個示例util類
public class JwtUtil {
private final static String secretKey = "[email protected]#*&^&%^&BHv*h)dk782GYh";
/**
* 加密演算法
*/
private static Algorithm algorithm = Algorithm.HMAC256(secretKey);
/**
* 過期時間單位
*/
private static int expiresUnit = Calendar.DAY_OF_YEAR;
/**
* 過期時間值
*/
private static int expireAmount = 7;
/**
* 生成token
* @param param payload中攜帶的資料對
* @return
*/
public static String generateToken(Map<String,String> param){
JWTCreator.Builder builder = JWT.create();
param.forEach((k,v)->{
builder.withClaim(k,v);
});
Calendar instance = Calendar.getInstance();
instance.add(expiresUnit,expireAmount);
builder.withExpiresAt(instance.getTime());
String token = builder.sign(algorithm);
return token;
}
/**
* 生成token,payload中只有一組資訊
* @param key 攜帶資料的key
* @param value 攜帶資料的值
* @return
*/
public static String generateToken(String key, String value){
JWTCreator.Builder builder = JWT.create();
Calendar instance = Calendar.getInstance();
instance.add(expiresUnit,expireAmount);
builder.withClaim(key,value);
builder.withExpiresAt(instance.getTime());
String token = builder.sign(algorithm);
return token;
}
/**
* 驗證token,驗證失敗會丟擲異常
* @param token 需要驗證的token
* @return 解碼後的token,可以獲取寫入的值
*/
public static DecodedJWT verifyToken(String token){
DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
return decodedJWT;
}
}
攔截器
配置了jwt後,使用攔截器對使用者的token進行驗證
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map<String,Object> map = new HashMap<>();
String token = request.getHeader("token");
try{
DecodedJWT decodedJWT = JwtUtil.verifyToken(token);
//放行
return true;
}catch (SignatureVerificationException e){
map.put("msg","無效簽名");
}catch (TokenExpiredException e){
map.put("msg","token過期");
}catch (AlgorithmMismatchException e){
map.put("msg","token演算法不一致");
}catch (Exception e){
map.put("msg","無效token");
}
map.put("status",false);
//返回json資料
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print(json);
return false;
}
}
攔截配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/");
}
}