Springboot整合JWT
1. 添加依赖
<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>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.19.2</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2. 封装JWT工具类
package com.example.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Map;
public class JWTUtils {
private static final String SIGN = "$%!FDGS^@G!GF!AFDSF&%^F";
private JWTUtils() {
}
public static String getToken(Map<String, String> map) {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 7);
JWTCreator.Builder builder = JWT.create();
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
String token = builder
.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(SIGN));
return token;
}
public static DecodedJWT verifyToken(String token) {
return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
}
3. 使用拦截器验证token
若验证 token 的操作放在 Controller 中,将会有大量的代码冗余。所以验证 token 的操作应该放在拦截器中:
package com.example.interceptors;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.utils.JWTUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
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 = JWTUtils.verifyToken(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", "算法不一致!");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token无效!");
}
map.put("state", false);
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print(json);
return false;
}
}
4. 配置拦截器
设置拦截器的拦截路径和放行路径:
package com.example.config;
import com.example.interceptors.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("student/login");
}
}
5. 在controller中获取数据
package com.example.controller;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.entity.Student;
import com.example.service.StudentService;
import com.example.utils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/student")
@Slf4j
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping("/login")
public Map<String, Object> login(Student student) {
log.info(student.getName() + "," + student.getPassword());
Map<String, Object> map = new HashMap<>();
try {
Student studentDB = studentService.login(student);
Map<String, String> payload = new HashMap<>();
payload.put("id", studentDB.getId());
payload.put("name", studentDB.getName());
String token = JWTUtils.getToken(payload);
map.put("state", true);
map.put("msg", "认证成功");
map.put("token", token);
} catch (Exception e) {
e.printStackTrace();
map.put("state", false);
map.put("msg", "认证失败");
}
return map;
}
@PostMapping("/test")
public Map<String, Object> test(HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
Map<String, Object> data = new HashMap<>();
String token = request.getHeader("token");
DecodedJWT decodedJWT = JWTUtils.verifyToken(token);
Claim id = decodedJWT.getClaim("id");
Claim name = decodedJWT.getClaim("name");
data.put("id", id.asString());
data.put("name", name.asString());
map.put("state", true);
map.put("msg", "请求成功!");
map.put("data", data);
return map;
}
}
6. 使用postman测试接口
注意: token最好不要作为请求参数进行传递,最好放在请求头中。 感谢观看!
|