🧑🎓 个人主页:花棉袄
📖 本章内容:【SpringBoot整合JWT实现登陆验证】
✍🏻 版权: 本文由【花棉袄】原创💝在CSDN首发💝需要转载请联系博主
🌳 Jwt的头部承载两部分信息
🌳载荷就是存放有效信息的地方
iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
定义数据:存放我们想放在token中存放的key-value值
🌳 签证信息
<dependency>
<groupId>com.auth0groupId>
<artifactId>java-jwtartifactId>
<version>3.10.3version>
dependency>
/**
* @Author 天才小狐狸
* @Data 2022/8/6 1:54
* @Description 需要登录才能进行操作的注解LoginToken
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginToken {
boolean required() default true;
}
/**
* @Author 天才小狐狸
* @Data 2022/8/6 1:57
* @Description 用来跳过验证的PassToken
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String userID;
private String userName;
private String passWord;
}
@Service
public class TokenService {
//5分钟之后过期
private static final long EXPIRE_TIME = 5 * 60 * 1000;
public String getToken(User user) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
String token = JWT.create().withAudience(user.getUserID())// 将 user id 保存到 token 里面
.withExpiresAt(date)
.sign(Algorithm.HMAC256(user.getPassWord()));// 以 password 作为 token 的密钥
return token;
}
}
@Service
public class UserService {
public User getUser(String userid ,String username, String password){
if ("admin".equals(username) && "admin".equals(password)){
User user=new User();
user.setUserID(userid);
user.setUserName(username);
user.setPassWord(password);
return user;
}
else{
return null;
}
}
public User getUser(String userid){
if ("admin".equals(userid)){
User user=new User();
user.setUserID("admin");
user.setUserName("admin");
user.setPassWord("admin");
return user;
}
else{
return null;
}
}
}
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private TokenService tokenService;
@Test
void getToken() {
User user = new User();
user.setUserID("1");
user.setPassWord("123");
String token = tokenService.getToken(user);
System.out.println(token);
}
}
/**
* @Author 天才小狐狸
* @Data 2022/8/6 2:14
* @Description
*/
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 http 请求头中取出 token
String token = request.getHeader("token");
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(LoginToken.class)) {
LoginToken loginToken = method.getAnnotation(LoginToken.class);
if (loginToken.required()) {
// 执行认证
if (token == null) {
throw new RuntimeException("无token,请重新登录");
}
// 获取 token 中的 user id
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
User user = userService.getUser(userId);
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassWord())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("401");
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
/**
* @title: InterceptorConfig
* @Author gjt
* @Date: 2020-12-21
* @Description:设置拦截规则&&注册拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
}
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
}
@RestController
public class Login {
@Autowired
private UserService userService;
@Autowired
private TokenService tokenService;
@PostMapping("/login")
public Result login(String userid, String username, String password) {
User user = userService.getUser(userid, username, password);
if (user == null) {
return Result.fail("message", "登录失败!");
} else {
String token = tokenService.getToken(user);
return Result.ok(token, "登录成功");
}
}
@LoginToken
@PostMapping("/getMessage")
public Result getMessage() {
return Result.ok("您已通过验证");
}
}