目錄
一、Springboot整合JWT
強烈建議小伙伴們閱讀 JWT 基礎概念:https://www.cnblogs.com/code-duck/p/13479792.html
再進行Springboot整合
1.創建Springboot項目
2.配置pom信息
<!--?xml version="1.0" encoding="UTF-8"?-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelversion>4.0.0</modelversion>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>2.3.1.RELEASE</version>
<relativepath>
</relativepath></parent>
<groupid>com.duck.code</groupid>
<artifactid>Springboot-JWT</artifactid>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
<!--引入jwt-->
<dependency>
<groupid>com.auth0</groupid>
<artifactid>java-jwt</artifactid>
<version>3.4.0</version>
</dependency>
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
<optional>true</optional>
</dependency>
<!--mybatis plus-->
<dependency>
<groupid>com.baomidou</groupid>
<artifactid>mybatis-plus-boot-starter</artifactid>
<version>3.3.2</version>
</dependency>
<!--代碼生成器-->
<dependency>
<groupid>com.baomidou</groupid>
<artifactid>mybatis-plus-generator</artifactid>
<version>3.3.2</version>
</dependency>
<!--逆向工程需要模板引擎-->
<dependency>
<groupid>org.freemarker</groupid>
<artifactid>freemarker</artifactid>
<version>2.3.30</version>
</dependency>
<!--mysql依賴-->
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
<scope>runtime</scope>
</dependency>
<!--連接池-->
<dependency>
<groupid>com.alibaba</groupid>
<artifactid>druid</artifactid>
<version>1.1.20</version>
</dependency>
</dependencies>
</project>
3.配置application配置文件信息
server:
port: 8081
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_jwt?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
global-config:
db-config:
table-prefix: tb_ # 表明前綴
type-aliases-package: com.code.duck.entity # 實體類所在包
mapper-locations: classpath*:/mapper/**Mapper.xml # xml文件所在位置
5.Springboot主啟動類配置
@SpringBootApplication
@MapperScan("com.duck.code.mapper")
public class JWTApplication {
public static void main(String[] args) {
SpringApplication.run(JWTApplication.class,args);
}
}
4.Springboot整合MybatisPlus
使用MybatisPlus代碼生成器,生成entity、controller、service,service.impl、mapper、xml文件
代碼生成器參考本人:Springboot整合MybatisPlus的文章 https://www.cnblogs.com/code-duck/p/13481550.html
6.封裝JWT工具類
JWTUtil工具類主要用於生成JWT令牌(token)、核實token信息、對token進行解密
JWT抽象類
JWT抽象類中的三個方法,對應於上述三個功能
public abstract class JWT {
/**
* Decode a given Json Web Token.
*
* @param token with jwt format as string.
* @return a decoded JWT.
*/
public static DecodedJWT decode(String token) throws JWTDecodeException {
return new JWTDecoder(token);
}
/**
* Returns a {@link JWTVerifier} builder with the algorithm to be used to validate token signature.
*
* @param algorithm that will be used to verify the token's signature.
* @return {@link JWTVerifier} builder
* @throws IllegalArgumentException if the provided algorithm is null.
*/
public static Verification require(Algorithm algorithm) {
return JWTVerifier.init(algorithm);
}
/**
* Returns a Json Web Token builder used to create and sign tokens
*
* @return a token builder.
*/
public static JWTCreator.Builder create() {
return JWTCreator.init();
}
}
JWTUtil工具類
public class JWTUtil {
// 用於JWT進行簽名加密的秘鑰
private static String SECRET = "code-duck-*%#@*!&";
/**
* @Param: 傳入需要設置的payload信息
* @return: 返回token
*/
public static String generateToken(Map<string, string=""> map) {
JWTCreator.Builder builder = JWT.create();
// 將map內的信息傳入JWT的payload中
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
// 設置JWT令牌的過期時間為60
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 60);
builder.withExpiresAt(instance.getTime());
// 設置簽名並返回token
return builder.sign(Algorithm.HMAC256(SECRET)).toString();
}
/**
* @Param: 傳入token
* @return:
*/
public static void verify(String token) {
JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}
/**
* @Param: 傳入token
* @return: 解密的token信息
*/
public static DecodedJWT getTokenInfo(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}
}
7.UserController控制器中聲明登錄接口
@RestController
@Slf4j
public class UserController {
@Resource
private UserService userService;
@PostMapping(value = "/user/login")
public Map<string, string=""> userLogin(@RequestBody User user) {
log.info(user.getUsername());
log.info(user.getPassword());
QueryWrapper<user> wrapper = new QueryWrapper<>();
wrapper.eq("username", user.getUsername());
wrapper.eq("password",user.getPassword());
// 數據庫中查詢用戶信息
User one = userService.getOne(wrapper);
HashMap<string, string=""> result = new HashMap<>(); // 返回結果信息給前端
if (one == null){
result.put("code","401");
result.put("msg","用戶名或密碼錯誤");
}
Map<string, string=""> map = new HashMap<>(); //用來存放payload信息
map.put("id",one.getId().toString());
map.put("username",one.getUsername());
map.put("role",one.getRole());
// 生成token令牌
String token = JWTUtil.generateToken(map);
// 返回前端token
result.put("code","200");
result.put("msg","登錄成功");
result.put("token",token);
return result;
}
}
8.啟動Springboot
使用postman進行接口測試,查看是否返回了正確響應,並生成了token令牌

二、為Springboot配置攔截器
- 當用戶登錄成功時,服務端為該用戶生成了一個時長為60的token令牌,
"token": "xxx.xxx.xx"的形式 以返回給前端系統 - 當前端在每次請求時,我們選擇將token令牌放至放入HTTP Header中的Authorization位
- 服務器對所有的請求進行攔截並校驗token(除登錄接口外)。如果token 信息不正確或過時,則向前端返回錯誤代碼,校驗正確則放行。
創建JWT攔截器
在此處進行token校驗,如果校驗成功則放行,否則返回異常信息給前端系統
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map<string, string=""> map = new HashMap<>();
//獲取請求頭中的token令牌
String token = request.getHeader("token");
try {
JWTUtil.verify(token);//驗證令牌
return true;//放行請求
} catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msg", "無效簽名!");
} catch (TokenExpiredException e) {
e.printStackTrace();
map.put("msg", "token過期!");
} catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg", "token算法不一致!");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token無效!!");
}
map.put("code", "403");//設置狀態
//將 map 轉為json jackson
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
配置WebMvcConfigurer攔截器
在此處配置過濾規則:即添加JWTInterceptor token校驗攔截器、攔截非登錄接口外的一切/user接口
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
.excludePathPatterns("/user/login") // 登錄接口不用於token驗證
.addPathPatterns("/user/**"); // 其他非登錄接口都需要進行token驗證
}
}
在控制器中添加測試接口
@GetMapping(value = "/user/test")
public Map<string,string> test(HttpServletRequest request){
Map<string, string=""> map = new HashMap<>();
//處理自己業務邏輯
String token = request.getHeader("token");
DecodedJWT claims = JWTUtil.getTokenInfo(token);
log.info("用戶id: [{}]",claims.getClaim("id").asString());
log.info("用戶name: [{}]",claims.getClaim("username").asString());
log.info("用戶role: [{}]",claims.getClaim("role").asString());
map.put("code","200");
map.put("msg","請求成功!");
return map;
}
啟動Springboot進行測試
- 訪問http://localhost:8081/user/login進行登錄測試,獲取服務器端返回的token信息
- 測試http://localhost:8081/user/test,在其請求頭配置token信息
</string,></string,string></string,></string,></string,></string,></string,>
