JSON Web Token(JWT)是一個(gè)非常輕巧的規(guī)范。這個(gè)規(guī)范允許我們使用JWT在用戶和服務(wù)器之間傳遞安全可靠的信息。
JWT的組成
一個(gè)JWT實(shí)際上就是一個(gè)字符串,它由三部分組成,頭部、載荷與簽名。簡單說明就到此為止,下面我們簡單介紹如何使用JWT。
1、引入相關(guān)的包
在pom.xml中引入JWT的包,和SpringMVC包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.0</version>
</dependency>
2、定義加密的秘鑰
這個(gè)可以省略,可以使用用戶的密碼作為加密秘鑰。
public class ConstantKey {
public static final String PICEA_JWT_KEY = "spring-boot-jwt-key~#^";
}
3、直接在控制類里面引入JWT生成方法
主要說明JWT.create()方法,注釋中說明了
withAudience(name)// 將 user id 保存到 token 里面
withExpiresAt(new Date(System.currentTimeMillis() + 2 * 60 * 1000))//定義token的有效期
sign(Algorithm.HMAC256(ConstantKey.PICEA_JWT_KEY));// 加密秘鑰,也可以使用用戶保持在數(shù)據(jù)庫中的密碼字符串。
最后我們得到的JWT,其實(shí)是如下一串字符串。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ6aGFuZ3NhbiIsImV4cCI6MTU1NTQ5MzI0OH0.FZISiYvyLJcrARe0nC8umMZ_MdR0YMkjMXI2mXYUncE
控制類的代碼如下。
@RestController
public class PiceaContoller {
@RequestMapping("/login")
public Object login(String name, String password) throws Exception {
/**
* 這里為了簡單,就不驗(yàn)證用戶名和密碼的正確性了,實(shí)際驗(yàn)證跟其他的方式一樣,
* 就是比對一下輸入的用戶名密碼跟數(shù)據(jù)的數(shù)據(jù)是否一樣
*/
String token = "";
token = JWT.create()
.withAudience(name)// 將 user id 保存到 token 里面
.withExpiresAt(new Date(System.currentTimeMillis() + 2 * 60 * 1000))//定義token的有效期
.sign(Algorithm.HMAC256(ConstantKey.PICEA_JWT_KEY));// 加密秘鑰,也可以使用用戶保持在數(shù)據(jù)庫中的密碼字符串
return token;
}
@RequestMapping("/queryPicea")
public String queryPicea() {
String ret = "通過驗(yàn)證";
return ret;
}
}
4、使用攔截器實(shí)現(xiàn)認(rèn)證
如果你對攔截器還不明白,請移步Spring Boot使用處理器攔截器HandlerInterceptor。
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
String token = httpServletRequest.getHeader("token");// 從 http 請求頭中取出 token
// 如果不是映射到方法直接通過
if(!(object instanceof HandlerMethod)){
return true;
}
HandlerMethod handlerMethod=(HandlerMethod)object;
Method method=handlerMethod.getMethod();
//檢查方法名是否是“l(fā)ogin”如果是則跳過,也可以加注解,用注解過濾不需要權(quán)限的方法
if ("login".equals(method.getName())) {
return true;
}
// 執(zhí)行認(rèn)證
if (token == null) {
throw new RuntimeException("無token,請重新登錄");
}
// 獲取 token 中的 name
String name;
try {
name = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
// 驗(yàn)證 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(ConstantKey.PICEA_JWT_KEY)).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("401");
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
5、建立InterceptorConfig注冊攔截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
6、進(jìn)行功能測試
首先我們之間執(zhí)行查詢,這里測試需要使用到post工具了,我用的是ApiPost。
1)無token的情況,直接請求查詢

2)登錄,獲得token

3)帶著token請求

其它注意
本文章樣例:
工程名:spring-boot-jwt
GitHub:https://github.com/zzyjb/SpringBootLearning