自定义注解+拦截器实现用户鉴权

拦截器

注册拦截器

InterceptorConfig.java
package com.example.springboot.sercurity;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 拦截所有请求
		registry.addInterceptor(authInterceptor).addPathPatterns("/api/**");
    }

}

拦截器执行过程

  1. 1.preHandle
  2. 2.执行处理器逻辑(return前的语句)
  3. 3.postHandle
  4. 4.视图解析和试图渲染(return的页面)
  5. 5.afterCompletion

自定义拦截器

AuthInterceptor.java
package com.example.springboot.sercurity;

import com.example.springboot.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.Method;

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Autowired
    private UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception{
        // 获取token
        String token = request.getHeader("token");
         //如果不是映射到Controller直接放行
		//如果没有这句类型判断,当处理跨域请求时,类型转换会报错
        if(!(object instanceof HandlerMethod handlerMethod)){
            return true;
        }
        // 检查是否需要验证token
        Method method = handlerMethod.getMethod();
        //是否存在VerifyAdminToken注解,这个注解后文会说明
        if(method.isAnnotationPresent(VerifyAdminToken.class)){
            // 获取注解,验证token是否符合注解要求
            String str = checkToken(method.getAnnotation(VerifyAdminToken.class),token);
            if(!StringUtils.isEmpty(str)) throw new RuntimeException(str);
            return true;
        }
        return true;
    }

    // 检验token
    public String checkToken(VerifyAdminToken loginToken,String token){
        if(loginToken.required()){
            if(token == null)return "该请求没有token,请先获取token";
            if(userService.GetUserByToken(token)==null)return "未找到持有该token的用户";
            if(userService.GetUserByToken(token).getLevel()>=loginToken.level()){// token用户等级大于有效,判断是否要刷新令牌
                return null;
            }else{
                return "无效令牌";
            }
        }
        return null;
    }
}

代码中的

        if(!(object instanceof HandlerMethod handlerMethod)){
            return true;
        }
        // 检查是否需要验证token
        Method method = handlerMethod.getMethod();

原本是这句
HandlerMethod handlerMethod = (HandlerMethod)object;
跨域请求就会类型转换错误

java.lang.ClassCastException: class org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler cannot be cast to class org.springframework.web.method.HandlerMethod (org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler and org.springframework.web.method.HandlerMethod are in unnamed module of loader 'app')

当加入@CrossOrigin后,传到拦截器的object类型改变

多个拦截器的顺序

处理器前方法先注册先执行,处理器后方法和完成方法先注册后执行。若返回false,后续的处理器后方法和目标方法都不会执行,完成方法只执行返回true的拦截器的完成方法,而且顺序是先注册后执行。

自定义注解

注解(Annotation)是 Java 语言中的一个特性,用于为程序元素(类、方法、成员变量等)添加额外的信息,提供元数据。注解本身并不提供实际的逻辑功能,而是为其他工具或框架提供信息。

这是一个自定义注解 VerifyAdminToken,用于标识需要进行管理员令牌验证的类或方法。

VerifyAdminToken.java
package com.example.springboot.sercurity;

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 VerifyAdminToken {
    boolean required() default true;
    int level() default 6;
}

@Target({ElementType.METHOD, ElementType.TYPE}) 表示这个注解可以标注在方法和类上。
@Retention(RetentionPolicy.RUNTIME) 表示这个注解将被保留到运行时。这样,在运行时可以通过反射获取到这个注解的信息。

boolean required() default true; 定义了一个必需的属性 required,默认值为 true。表示是否需要进行管理员令牌验证。
int level() default 6; 定义了一个可选的属性 level,默认值为 6。表示验证的级别。

通过method.getAnnotation(VerifyAdminToken.class)获取到对象的注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值