添加solon适配及demo

This commit is contained in:
noear
2021-05-30 21:24:04 +08:00
parent 0748f7941d
commit a2d1121b66
24 changed files with 1360 additions and 1 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-starter</artifactId>
<version>1.19.0</version>
</parent>
<packaging>jar</packaging>
<name>sa-token-solon-plugin</name>
<artifactId>sa-token-solon-plugin</artifactId>
<description>solon integrate sa-token</description>
<dependencies>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon</artifactId>
<version>1.4.8</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>1.19.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,60 @@
package cn.dev33.satoken.solon;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.solon.integration.SaTokenMethodInterceptor;
import cn.dev33.satoken.solon.integration.SaContextForSolon;
import cn.dev33.satoken.stp.StpInterface;
import org.noear.solon.Solon;
import org.noear.solon.SolonApp;
import org.noear.solon.core.Aop;
import org.noear.solon.core.Plugin;
/**
* @author noear
* @since 1.4
*/
public class XPluginImp implements Plugin {
@Override
public void start(SolonApp app) {
Aop.context().beanAroundAdd(SaCheckPermission.class, SaTokenMethodInterceptor.instance);
Aop.context().beanAroundAdd(SaCheckRole.class, SaTokenMethodInterceptor.instance);
Aop.context().beanAroundAdd(SaCheckLogin.class, SaTokenMethodInterceptor.instance);
//集成初始化
//注入配置Bean
SaTokenConfig saTokenConfig = Solon.cfg().getBean("solon.sa-token", SaTokenConfig.class);
SaManager.setConfig(saTokenConfig);
//注入容器交互Bean
SaManager.setSaTokenContext(new SaContextForSolon());
//注入侦听器Bean
Aop.getAsyn(SaTokenListener.class, bw->{
SaManager.setSaTokenListener(bw.raw());
});
//注入框架行为Bean
Aop.getAsyn(SaTokenAction.class, bw->{
SaManager.setSaTokenAction(bw.raw());
});
//注入权限认证Bean
Aop.getAsyn(StpInterface.class, bw->{
SaManager.setStpInterface(bw.raw());
});
//注入持久化Bean
Aop.getAsyn(SaTokenDao.class, bw->{
SaManager.setSaTokenDao(bw.raw());
});
}
}

View File

@@ -0,0 +1,48 @@
package cn.dev33.satoken.solon.integration;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.solon.model.SaRequestForSolon;
import cn.dev33.satoken.solon.model.SaResponseForSolon;
import cn.dev33.satoken.solon.model.SaStorageForSolon;
import org.noear.solon.core.util.PathAnalyzer;
/**
* @author noear
* @since 1.4
*/
public class SaContextForSolon implements SaTokenContext {
/**
* 获取当前请求的Request对象
*/
@Override
public SaRequest getRequest() {
return new SaRequestForSolon();
}
/**
* 获取当前请求的Response对象
*/
@Override
public SaResponse getResponse() {
return new SaResponseForSolon();
}
/**
* 获取当前请求的 [存储器] 对象
*/
@Override
public SaStorage getStorage() {
return new SaStorageForSolon();
}
/**
* 校验指定路由匹配符是否可以匹配成功指定路径
*/
@Override
public boolean matchPath(String pattern, String path) {
return PathAnalyzer.get(path).matches(path);
}
}

View File

@@ -0,0 +1,22 @@
package cn.dev33.satoken.solon.integration;
import cn.dev33.satoken.SaManager;
import org.noear.solon.core.aspect.Interceptor;
import org.noear.solon.core.aspect.Invocation;
/**
* @author noear
* @since 1.4
*/
public class SaTokenMethodInterceptor implements Interceptor {
public static final SaTokenMethodInterceptor instance = new SaTokenMethodInterceptor();
@Override
public Object doIntercept(Invocation inv) throws Throwable {
// 注解鉴权
SaManager.getSaTokenAction().checkMethodAnnotation(inv.method().getMethod());
// 执行原有逻辑
return inv.invoke();
}
}

View File

@@ -0,0 +1,162 @@
package cn.dev33.satoken.solon.integration;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
import cn.dev33.satoken.router.SaRouterUtil;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Filter;
import org.noear.solon.core.handle.FilterChain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author noear 2021/5/30 created
*/
public class SaTokenPathFilter implements Filter {
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
/**
* 拦截路由
*/
private List<String> includeList = new ArrayList<>();
/**
* 放行路由
*/
private List<String> excludeList = new ArrayList<>();
/**
* 添加 [拦截路由]
* @param paths 路由
* @return 对象自身
*/
public SaTokenPathFilter addInclude(String... paths) {
includeList.addAll(Arrays.asList(paths));
return this;
}
/**
* 添加 [放行路由]
* @param paths 路由
* @return 对象自身
*/
public SaTokenPathFilter addExclude(String... paths) {
excludeList.addAll(Arrays.asList(paths));
return this;
}
/**
* 写入 [拦截路由] 集合
* @param pathList 路由集合
* @return 对象自身
*/
public SaTokenPathFilter setIncludeList(List<String> pathList) {
includeList = pathList;
return this;
}
/**
* 写入 [放行路由] 集合
* @param pathList 路由集合
* @return 对象自身
*/
public SaTokenPathFilter setExcludeList(List<String> pathList) {
excludeList = pathList;
return this;
}
/**
* 获取 [拦截路由] 集合
* @return see note
*/
public List<String> getIncludeList() {
return includeList;
}
/**
* 获取 [放行路由] 集合
* @return see note
*/
public List<String> getExcludeList() {
return excludeList;
}
// ------------------------ 钩子函数
/**
* 认证函数:每次请求执行
*/
public SaFilterAuthStrategy auth = r -> {};
/**
* 异常处理函数:每次[认证函数]发生异常时执行此函数
*/
public SaFilterErrorStrategy error = e -> {
throw new SaTokenException(e);
};
/**
* 前置函数:在每次[认证函数]之前执行
*/
public SaFilterAuthStrategy beforeAuth = r -> {};
/**
* 写入[认证函数]: 每次请求执行
* @param auth see note
* @return 对象自身
*/
public SaTokenPathFilter setAuth(SaFilterAuthStrategy auth) {
this.auth = auth;
return this;
}
/**
* 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数
* @param error see note
* @return 对象自身
*/
public SaTokenPathFilter setError(SaFilterErrorStrategy error) {
this.error = error;
return this;
}
/**
* 写入[前置函数]:在每次[认证函数]之前执行
* @param beforeAuth see note
* @return 对象自身
*/
public SaTokenPathFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
this.beforeAuth = beforeAuth;
return this;
}
@Override
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
try {
// 执行全局过滤器
SaRouterUtil.match(includeList, excludeList, () -> {
beforeAuth.run(null);
auth.run(null);
});
} catch (Throwable e) {
// 1. 获取异常处理策略结果
Object result = error.run(e);
String resultString = String.valueOf(result);
// 2. 写入输出流
ctx.contentType("text/plain; charset=utf-8");
ctx.output(resultString);
return;
}
// 执行
chain.doFilter(ctx);
}
}

View File

@@ -0,0 +1,45 @@
package cn.dev33.satoken.solon.model;
import cn.dev33.satoken.context.model.SaRequest;
import org.noear.solon.core.handle.Context;
/**
* @author noear
* @since 1.4
*/
public class SaRequestForSolon implements SaRequest {
Context ctx;
public SaRequestForSolon(){
ctx = Context.current();
}
@Override
public Object getSource() {
return ctx;
}
@Override
public String getParameter(String s) {
return ctx.param(s);
}
@Override
public String getHeader(String s) {
return ctx.header(s);
}
@Override
public String getCookieValue(String s) {
return ctx.cookie(s);
}
@Override
public String getRequestPath() {
return ctx.pathNew();
}
@Override
public String getMethod() {
return ctx.method();
}
}

View File

@@ -0,0 +1,42 @@
package cn.dev33.satoken.solon.model;
import cn.dev33.satoken.context.model.SaResponse;
import org.noear.solon.Utils;
import org.noear.solon.core.handle.Context;
/**
* @author noear
* @since 1.4
*/
public class SaResponseForSolon implements SaResponse {
Context ctx;
public SaResponseForSolon() {
ctx = Context.current();
}
@Override
public Object getSource() {
return ctx;
}
@Override
public void deleteCookie(String s) {
ctx.cookieRemove(s);
}
@Override
public void addCookie(String name, String value, String path, String domain, int timeout) {
if (Utils.isNotEmpty(path)) {
path = "/";
}
ctx.cookieSet(name, value, domain, path, timeout);
}
@Override
public SaResponse setHeader(String name, String value) {
ctx.headerSet(name, value);
return this;
}
}

View File

@@ -0,0 +1,36 @@
package cn.dev33.satoken.solon.model;
import cn.dev33.satoken.context.model.SaStorage;
import org.noear.solon.core.handle.Context;
/**
* @author noear
* @since 1.4
*/
public class SaStorageForSolon implements SaStorage {
Context ctx;
public SaStorageForSolon() {
ctx = Context.current();
}
@Override
public Object getSource() {
return ctx;
}
@Override
public void set(String key, Object value) {
ctx.attrSet(key, value);
}
@Override
public Object get(String key) {
return ctx.attr(key);
}
@Override
public void delete(String key) {
ctx.attrMap().remove(key);
}
}

View File

@@ -0,0 +1,4 @@
/**
* sa-token集成SpringBoot的各个组件
*/
package cn.dev33.satoken.solon;

View File

@@ -0,0 +1 @@
solon.plugin=cn.dev33.satoken.solon.XPluginImp