springboot项目里想加个token拦截,用的是注解拦截的方法,目前的问题是在
在controller方法接口头上添加了这个注解,也就是说没有登录不能访问这个接口。但实际效果是可以访问。求点拨。
@UserLoginToken(required = false)
注解如下
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,
所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
这是处理工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.vue02demo.annotation.PassToken;
import com.example.vue02demo.annotation.UserLoginToken;
import com.example.vue02demo.entity.User;
import com.example.vue02demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
UserService userService;
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();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(UserLoginToken.class)) {
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.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.findUserById(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;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
把你controller层代码放出来呀。提问题要全面点。
还有你是先判断@PassToken 注解的,如果controller加入了这个注解,就算你加上@UserLoginToken 也会访问到。
我这边是这么写的:
使用拦截器时,你要注意,拦截器是有配置那些接口需要拦截,哪些接口不需要拦截,如果你当前访问的接口是放开的,那访问时,是不会走拦截器的逻辑的,具体配置拦截的类需要实现接口WebMvcConfigurer,如果没有实现这个类,那么springmvc会采用默认的拦截器进行拦截,也就是默认放开
引用GPT作答@UserLoginToken(required = false)
是一个注解,通常用于标记需要用户登录才能访问的接口或方法。在这个例子中,required = false
表示该接口或方法可以选择是否需要用户登录。如果设置为 true
,则表示该接口或方法需要用户登录才能访问;如果设置为 false
,则表示该接口或方法可以在用户未登录的情况下访问。
这个注解通常与身份验证和授权功能一起使用,以确保只有经过身份验证和授权的用户才能访问特定的接或方法。
required = false 改成 required = true 之后,重新编译运行试试, 由于设置为了 非必须传递的参数~,望采纳
【相关推荐】
第一:@UserLoginToken(required = false),第二:preHandle前面是不是少@Override,总感觉你是没有进入拦截器里面,不行你就跟代码吧
拦截器配置了吗?