sa-token-solon-plugin 适配自定义注解扩展

This commit is contained in:
click33
2024-08-04 01:42:30 +08:00
parent 16b1e4f99c
commit f926a3f136
8 changed files with 114 additions and 45 deletions

View File

@@ -19,6 +19,7 @@ import cn.dev33.satoken.annotation.*;
import cn.dev33.satoken.annotation.handler.*;
import cn.dev33.satoken.fun.strategy.SaCheckMethodAnnotationFunction;
import cn.dev33.satoken.fun.strategy.SaGetAnnotationFunction;
import cn.dev33.satoken.fun.strategy.SaIsAnnotationPresentFunction;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import java.lang.annotation.Annotation;
@@ -121,4 +122,12 @@ public final class SaAnnotationStrategy {
return element.getAnnotation(annotationClass);
};
/**
* 判断一个 Method 或其所属 Class 是否包含指定注解
*/
public SaIsAnnotationPresentFunction isAnnotationPresent = (method, annotationClass) -> {
return instance.getAnnotation.apply(method, annotationClass) != null ||
instance.getAnnotation.apply(method.getDeclaringClass(), annotationClass) != null;
};
}

View File

@@ -0,0 +1,33 @@
package com.pj.satoken.custom_annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 账号校验:在标注一个方法上时,要求前端必须提交相应的账号密码参数才能访问方法。
*
* @author click33
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface CheckAccount {
/**
* 需要校验的账号
*
* @return /
*/
String name();
/**
* 需要校验的密码
*
* @return /
*/
String pwd();
}

View File

@@ -0,0 +1,42 @@
package com.pj.satoken.custom_annotation.handler;
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.SaTokenException;
import com.pj.satoken.custom_annotation.CheckAccount;
import org.noear.solon.annotation.Component;
import java.lang.reflect.Method;
/**
* 注解 CheckAccount 的处理器
*
* @author click33
*
*/
@Component
public class CheckAccountHandler implements SaAnnotationAbstractHandler<CheckAccount> {
// 指定这个处理器要处理哪个注解
@Override
public Class<CheckAccount> getHandlerAnnotationClass() {
return CheckAccount.class;
}
// 每次请求校验注解时,会执行的方法
@Override
public void checkMethod(CheckAccount at, Method method) {
// 获取前端请求提交的参数
String name = SaHolder.getRequest().getParamNotNull("name");
String pwd = SaHolder.getRequest().getParamNotNull("pwd");
// 与注解中指定的值相比较
if(name.equals(at.name()) && pwd.equals(at.pwd()) ) {
// 校验通过,什么也不做
} else {
// 校验不通过,则抛出异常
throw new SaTokenException("账号或密码错误,未通过校验");
}
}
}

View File

@@ -15,10 +15,10 @@
*/
package cn.dev33.satoken.oauth2.logic;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
@@ -27,11 +27,7 @@ import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Api;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.GrantType;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.Param;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Consts.ResponseType;
import cn.dev33.satoken.oauth2.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.model.ClientTokenModel;
import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.oauth2.model.SaClientModel;
import cn.dev33.satoken.oauth2.model.*;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
@@ -179,7 +175,7 @@ public class SaOAuth2Handle {
*/
public static Object token(SaRequest req, SaResponse res, SaOAuth2Config cfg) {
// 获取参数
String authorizationValue = SaBasicUtil.getAuthorizationValue();
String authorizationValue = SaHttpBasicUtil.getAuthorizationValue();
String clientId;
String clientSecret;
// gitlab回调token接口时,按照的是标准的oauth2协议的basic请求头,basic中会包含client_id和client_secret的信息

View File

@@ -16,11 +16,12 @@
package cn.dev33.satoken.solon;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicTemplate;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicTemplate;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
import cn.dev33.satoken.httpauth.digest.SaHttpDigestTemplate;
import cn.dev33.satoken.httpauth.digest.SaHttpDigestUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
@@ -36,6 +37,7 @@ import cn.dev33.satoken.solon.sso.SaSsoAutoConfigure;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import cn.dev33.satoken.temp.SaTempInterface;
import org.noear.solon.Solon;
import org.noear.solon.core.AppContext;
@@ -95,6 +97,11 @@ public class XPluginImp implements Plugin {
SaTokenEventCenter.registerListener(sl);
});
// 注入自定义注解处理器 Bean (可以有多个)
context.subBeansOfType(SaAnnotationAbstractHandler.class, sl -> {
SaAnnotationStrategy.instance.registerAnnotationHandler(sl);
});
// 注入权限认证 Bean
context.getBeanAsync(StpInterface.class, bean -> {
SaManager.setStpInterface(bean);

View File

@@ -23,6 +23,7 @@ import cn.dev33.satoken.filter.SaFilterAuthStrategy;
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
import cn.dev33.satoken.filter.SaFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import cn.dev33.satoken.strategy.SaStrategy;
import org.noear.solon.Solon;
import org.noear.solon.core.handle.*;
@@ -202,16 +203,13 @@ public class SaTokenFilter implements SaFilter, Filter { //之所以改名,为
private boolean authAnno(Action action) {
//2.验证注解处理
if (isAnnotation && action != null) {
// 获取此请求对应的 Method 处理函数
Method method = action.method().getMethod();
// 如果此 Method 或其所属 Class 标注了 @SaIgnore则忽略掉鉴权
if (SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
// 注解校验
try{
Method method = action.method().getMethod();
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
} catch (StopMatchException ignored) {
return false;
}
// 注解校验
SaStrategy.instance.checkMethodAnnotation.accept(method);
}
return true;

View File

@@ -15,7 +15,6 @@
*/
package cn.dev33.satoken.solon.integration;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.StopMatchException;
@@ -23,7 +22,7 @@ import cn.dev33.satoken.filter.SaFilter;
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import org.noear.solon.core.handle.*;
import org.noear.solon.core.route.RouterInterceptor;
import org.noear.solon.core.route.RouterInterceptorChain;
@@ -237,16 +236,13 @@ public class SaTokenInterceptor implements SaFilter, RouterInterceptor {
private boolean authAnno(Action action) {
//2.验证注解处理
if (isAnnotation && action != null) {
// 获取此请求对应的 Method 处理函数
Method method = action.method().getMethod();
// 如果此 Method 或其所属 Class 标注了 @SaIgnore则忽略掉鉴权
if (SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
// 注解校验
try{
Method method = action.method().getMethod();
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
} catch (StopMatchException ignored) {
return false;
}
// 注解校验
SaStrategy.instance.checkMethodAnnotation.accept(method);
}
return true;

View File

@@ -15,18 +15,16 @@
*/
package cn.dev33.satoken.interceptor;
import java.lang.reflect.Method;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* Sa-Token 综合拦截器,提供注解鉴权和路由拦截鉴权能力
@@ -96,18 +94,8 @@ public class SaInterceptor implements HandlerInterceptor {
// 这里必须确保 handler 是 HandlerMethod 类型时,才能进行注解鉴权
if(isAnnotation && handler instanceof HandlerMethod) {
// 获取此请求对应的 Method 处理函数
Method method = ((HandlerMethod) handler).getMethod();
// 如果此 Method 或其所属 Class 标注了 @SaIgnore则忽略掉鉴权
if(SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
// 注意这里直接就退出整个鉴权了,最底部的 auth.run() 路由拦截鉴权也被跳出了
return true;
}
// 注解校验
SaStrategy.instance.checkMethodAnnotation.accept(method);
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
}
// Auth 校验