首先定义匿名注解
/**
* 允许加入此注解的接口匿名访问
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface SaAnonymousAccess {
}
然后我们根据SaToken的插件制作文档开发一个插件类
import cn.dev33.satoken.strategy.SaStrategy;
import org.springframework.web.method.HandlerMethod;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class SaAnonymousPlugin {
// 路由鉴权是否开启匿名注解的标志
public static boolean startRouteCheck = false;
/**
* 若当前请求携带匿名注解则返回 false(不需要后续鉴权), 否则返回 true(需要后续鉴权)
*
* 路由拦截器需要额外如下代码:
*
* new SaRouteInterceptor((req, res, handler) -> {
* if (!SaAnonymousPlugin.isRouteAnon(handler)) {
* // 和之前一样
* SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
* }
* })
*
* @param handler
* @return
*/
public static boolean routeCheckAnon(Object handler) {
if (startRouteCheck) {
// 获取处理method
if (!(handler instanceof HandlerMethod)) {
return true;
}
Method method = ((HandlerMethod) handler).getMethod();
if (checkAnonymous(method) || checkAnonymous(method.getDeclaringClass())) {
return false;
}
}
return true;
}
/**
* 开启匿名注解
*/
public static void start() {
startRouteCheck = true;
// 注解
SaStrategy.me.checkMethodAnnotation = (method) -> {
if (checkAnonymous(method) || checkAnonymous(method.getDeclaringClass())) {
return;
}
// 先校验 Method 上的注解
SaStrategy.me.checkElementAnnotation.accept(method);
// 再校验 Method 所属 Class 上的注解
SaStrategy.me.checkElementAnnotation.accept(method.getDeclaringClass());
};
}
/**
* 关闭匿名注解
*/
public static void stop() {
startRouteCheck = false;
SaStrategy.me.checkMethodAnnotation = (method) -> {
// 先校验 Method 所属 Class 上的注解
SaStrategy.me.checkElementAnnotation.accept(method.getDeclaringClass());
// 再校验 Method 上的注解
SaStrategy.me.checkElementAnnotation.accept(method);
};
}
/**
* 检查某个方法或者类对象是否携带匿名注解
* @param target
* @return
*/
private static boolean checkAnonymous(AnnotatedElement target) {
// 校验 @SaCheckLogin 注解
SaAnonymousAccess anonymousAccess = (SaAnonymousAccess) SaStrategy.me.getAnnotation.apply(target, SaAnonymousAccess.class);
return anonymousAccess != null;
}
}
注册拦截器
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册Sa-Token的注解拦截器,打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器(和之前一样)
registry.addInterceptor(new SaAnnotationInterceptor())
.addPathPatterns("/**");
// 注册路由拦截器(需要添加部分固定代码)
registry.addInterceptor(new SaRouteInterceptor((req, res, handler) -> {
if (SaAnonymousPlugin.routeCheckAnon(handler)) { // 插件实现
// 其他代码和之前一样
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
}
})).addPathPatterns("/**");
}
}
在启动类后面开启匿名功能
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
SaAnonymousPlugin.start(); // 开启匿名功能, stop() 方法关闭
}
}
请注意,本方案不支持全局过滤器
新版的SaToken框架已实现 @SaIgnore 注解, 无需自定义