什么是JWT
JSON Web Token (JWT)是一個(gè)開放標(biāo)準(zhǔn)(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對(duì)象在各方之間安全地傳輸信息。該信息可以被驗(yàn)證和信任,因?yàn)樗菙?shù)字簽名的。
什么時(shí)候應(yīng)該用JWT
Authorization (授權(quán)) : 這是使用JWT的最常見場景。一旦用戶登錄,后續(xù)每個(gè)請(qǐng)求都將包含JWT,允許用戶訪問該令牌允許的路由、服務(wù)和資源。單點(diǎn)登錄是現(xiàn)在廣泛使用的JWT的一個(gè)特性,因?yàn)樗拈_銷很小,并且可以輕松地跨域使用。
Information Exchange (信息交換) : 對(duì)于安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。因?yàn)镴WT可以被簽名,例如,用公鑰/私鑰對(duì),你可以確定發(fā)送人就是它們所說的那個(gè)人。另外,由于簽名是使用頭和有效負(fù)載計(jì)算的,您還可以驗(yàn)證內(nèi)容沒有被篡改。
JWT的結(jié)構(gòu)
JSON Web Token由三部分組成,它們之間用圓點(diǎn)(.)連接,如
xxxxx.yyyyy.zzzzz
這三部分分別是:
- Header
token的類型(“JWT”)和算法名稱(比如:HMAC SHA256或者RSA等等)
{
"alg": "HS256",
"typ": "JWT"
}
- Payload
實(shí)體(通常是用戶)和其他數(shù)據(jù)的聲明
{
"sub": '123456789',
"name": 'zhangsan',
"admin":true
}
- Signature
簽證信息
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
SpringBoot 基于JWT實(shí)現(xiàn)token驗(yàn)證
引入依賴
注意:這里引入的是java-jwt并非jjwt
<!--JWT鑒權(quán)-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
自定義token攔截器
獲取token并驗(yàn)證token
@Component
@Slf4j
public class TokenHandler implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token != null) {
boolean result = TokenUtil.verify(token);
//判斷綁定
if (result) {
log.info("通過攔截器");
return true;
}
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
JSONObject res = new JSONObject();
res.put("status", "-1");
res.put("msg", "鑒權(quán)失敗");
PrintWriter out = null;
out = response.getWriter();
out.write(res.toString());
out.flush();
out.close();
return false;
}
}
添加JWT token的工具類
用于生成和解析JWT token的工具類
@Slf4j
public class TokenUtil {
/**
* token秘鑰
*/
private static final String TOKEN_SECRET = "apiManager";
/**
* 設(shè)置過期時(shí)間
*/
private static final long EXPIRE_DATE=30*60*100000;
public static String token(String secreteKey) {
String token = "";
try {
//過期時(shí)間
Date date = new Date(System.currentTimeMillis()+EXPIRE_DATE);
//秘鑰及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//設(shè)置頭部信息
Map<String, Object> header = new HashMap<>();
header.put("typ", "JWT");
header.put("alg", "HS256");
//攜帶username,password信息,生成簽名
token = JWT.create()
.withHeader(header)
.withClaim("secreteKey", secreteKey)
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
log.error("獲取token異常", e);
return null;
}
return token;
}
public static boolean verify(String token) {
/**
* @desc 驗(yàn)證token,通過返回true
* @params [token]需要校驗(yàn)的串
**/
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {
log.error("驗(yàn)證token異常", e);
return false;
}
}
}
配置攔截器
用于設(shè)置攔截器的過濾路徑規(guī)則。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private TokenHandler tokenHandler;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(tokenHandler);
//攔截配置
registration.addPathPatterns("/api-manager/transpond/**");
//排除配置
registration.excludePathPatterns("/api-manager/api/**");
}
}