项目描述
上传时间
浏览人数
5.创建拦截器函数(在访问功能函数前,会检查是否有token注解,有则验证,无则跳过验证)
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
//prehandle函数会在Controller里的函数被调用之前提前调用
//所以在这里可以达到提前拦截的效果
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(TokenConfig.PassToken.class)) {
TokenConfig.PassToken passToken = method.getAnnotation(TokenConfig.PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查函数是否有UserLoginToken注解, 有则执行验证, 无则执行return true
if (method.isAnnotationPresent(TokenConfig.UserLoginToken.class)) {
TokenConfig.UserLoginToken userLoginToken = method.getAnnotation(TokenConfig.UserLoginToken.class);
if (userLoginToken.required()) {
// 执行认证
if (token == null) {
throw new RuntimeException("当前无token信息,请重新登录!");
}
// 获取 token 中的 userId
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("Token获取失败或有误!");
}
//通过token中的userId来验证是否存在
UserPojo userPojo = new UserPojo();
userPojo.setId(Long.parseLong(userId));
UserPojo up = userService.findUserById(userPojo);
if (up == null) {
throw new RuntimeException("当前用户ID不存在,请重新登录!");
}
// 通过token中的password与最新查询到password对比 来验证token的正确性
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(up.getPw())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("Token获取失败或已过期!");
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object o, Exception e) throws Exception {
}
}
6.添加拦截器函数的配置文件(设定拦截的访问路径范围)
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
//这里的 /** 代表的是拦截所有的访问路径
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
7.测试token功能
(1).在登录函数中加入生成token密文的代码,并将token存入返回的人员信息内(token会保存在cpu分配的内存中,再次登录后会重置token)
@PostMapping("login")
public JsonMsgPojo login(UserPojo up){
UserPojo userPojo = userService.login(up);
if (userPojo==null){
return new JsonMsgPojo(false,"用户名或密码错误!",null);
}
String token = TokenTools.getToken(userPojo);
userPojo.setToken(token);
return new JsonMsgPojo(true,"登陆成功!",userPojo);
}
(2).携带token访问需要token验证的函数(需要验证的函数需添加@TokenConfig.UserLoginToken注解,根据添加的自定义注解类名+函数名)
@GetMapping("findUser")
@TokenConfig.UserLoginToken
public JsonMsgPojo findUser(){
List<UserPojo> li = userService.findUser();
return new JsonMsgPojo(true,"成功!",li);
}
请注意需在Headers内添加token
携带token访问函数成功!
(3).不携带token访问需要token验证的函数
访问失败!
(4).token失效后访问需要token验证的函数
访问失败!