From db5e70db6a4269e558ba4db5a200dd7fea82ed7f Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Thu, 27 Feb 2025 05:55:55 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E9=98=B2?= =?UTF-8?q?=E7=81=AB=E5=A2=99=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20hooks=20=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/FirewallCheckException.java | 43 +++++++++ .../RequestPathInvalidException.java | 2 +- ...=> SaFirewallCheckFailHandleFunction.java} | 19 ++-- ...tion.java => SaFirewallCheckFunction.java} | 16 ++-- .../satoken/strategy/SaFirewallStrategy.java | 96 ++++++------------- .../strategy/hooks/SaFirewallCheckHook.java | 39 ++++++++ .../SaFirewallCheckHookForBlackList.java | 58 +++++++++++ ...SaFirewallCheckHookForDangerCharacter.java | 66 +++++++++++++ .../SaFirewallCheckHookForWhiteList.java | 58 +++++++++++ sa-token-demo/sa-token-demo-test/pom.xml | 5 - .../filter/SaPathCheckFilterForReactor.java | 6 +- .../filter/SaPathCheckFilterForReactor.java | 6 +- ...a => SaFirewallCheckFilterForServlet.java} | 33 +++++-- .../spring/SaTokenContextRegister.java | 6 +- .../SaPathCheckFilterForJakartaServlet.java | 6 +- 15 files changed, 350 insertions(+), 109 deletions(-) create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/exception/FirewallCheckException.java rename sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/{SaCheckRequestPathFunction.java => SaFirewallCheckFailHandleFunction.java} (59%) rename sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/{SaRequestPathInvalidHandleFunction.java => SaFirewallCheckFunction.java} (65%) create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHook.java create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForBlackList.java create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDangerCharacter.java create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForWhiteList.java rename sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/filter/{SaPathCheckFilterForServlet.java => SaFirewallCheckFilterForServlet.java} (56%) diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/FirewallCheckException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/FirewallCheckException.java new file mode 100644 index 00000000..810cd903 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/FirewallCheckException.java @@ -0,0 +1,43 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.exception; + +/** + * 一个异常:代表防火墙检验未通过 + * + * @author click33 + * @since 1.41.0 + */ +public class FirewallCheckException extends SaTokenException { + + /** + * 序列化版本号 + */ + private static final long serialVersionUID = 8243974276159004739L; + + public FirewallCheckException(String message) { + super(message); + } + + public FirewallCheckException(Throwable e) { + super(e); + } + + public FirewallCheckException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/RequestPathInvalidException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/RequestPathInvalidException.java index e09cf9e0..3f2b972d 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/exception/RequestPathInvalidException.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/RequestPathInvalidException.java @@ -21,7 +21,7 @@ package cn.dev33.satoken.exception; * @author click33 * @since 1.37.0 */ -public class RequestPathInvalidException extends SaTokenException { +public class RequestPathInvalidException extends FirewallCheckException { /** * 序列化版本号 diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaCheckRequestPathFunction.java b/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFailHandleFunction.java similarity index 59% rename from sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaCheckRequestPathFunction.java rename to sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFailHandleFunction.java index dcca032f..c77121e4 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaCheckRequestPathFunction.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFailHandleFunction.java @@ -15,25 +15,26 @@ */ package cn.dev33.satoken.fun.strategy; -import cn.dev33.satoken.exception.RequestPathInvalidException; +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.exception.FirewallCheckException; /** - * 函数式接口:校验请求 path 的算法 - * - *
如果属于无效请求 path,则抛出异常 RequestPathInvalidException
+ * 函数式接口:当防火墙校验不通过时执行的函数 * * @author click33 * @since 1.37.0 */ @FunctionalInterface -public interface SaCheckRequestPathFunction { +public interface SaFirewallCheckFailHandleFunction { /** * 执行函数 - * @param path 请求 path - * @param extArg1 扩展参数1 - * @param extArg2 扩展参数2 + * @param e 防火墙校验异常 + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 */ - void run(String path, Object extArg1, Object extArg2); + void run(FirewallCheckException e, SaRequest req, SaResponse res, Object extArg); } \ No newline at end of file diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaRequestPathInvalidHandleFunction.java b/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFunction.java similarity index 65% rename from sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaRequestPathInvalidHandleFunction.java rename to sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFunction.java index d3880465..bbb5aedc 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaRequestPathInvalidHandleFunction.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/fun/strategy/SaFirewallCheckFunction.java @@ -15,23 +15,25 @@ */ package cn.dev33.satoken.fun.strategy; -import cn.dev33.satoken.exception.RequestPathInvalidException; +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; /** - * 函数式接口:当请求 path 校验不通过时处理方案的算法 + * 函数式接口:防火墙校验函数 * * @author click33 * @since 1.37.0 */ @FunctionalInterface -public interface SaRequestPathInvalidHandleFunction { +public interface SaFirewallCheckFunction { /** * 执行函数 - * @param e 请求 path 无效的异常对象 - * @param extArg1 扩展参数1 - * @param extArg2 扩展参数2 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 */ - void run(RequestPathInvalidException e, Object extArg1, Object extArg2); + void execute(SaRequest req, SaResponse res, Object extArg); } \ No newline at end of file diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/SaFirewallStrategy.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/SaFirewallStrategy.java index 55e4da5f..d81f2912 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/SaFirewallStrategy.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/SaFirewallStrategy.java @@ -15,9 +15,16 @@ */ package cn.dev33.satoken.strategy; -import cn.dev33.satoken.exception.RequestPathInvalidException; -import cn.dev33.satoken.fun.strategy.SaCheckRequestPathFunction; -import cn.dev33.satoken.fun.strategy.SaRequestPathInvalidHandleFunction; +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.fun.strategy.SaFirewallCheckFailHandleFunction; +import cn.dev33.satoken.fun.strategy.SaFirewallCheckFunction; +import cn.dev33.satoken.strategy.hooks.SaFirewallCheckHook; +import cn.dev33.satoken.strategy.hooks.SaFirewallCheckHookForBlackList; +import cn.dev33.satoken.strategy.hooks.SaFirewallCheckHookForDangerCharacter; +import cn.dev33.satoken.strategy.hooks.SaFirewallCheckHookForWhiteList; + +import java.util.ArrayList; +import java.util.List; /** * Sa-Token 防火墙策略 @@ -27,9 +34,6 @@ import cn.dev33.satoken.fun.strategy.SaRequestPathInvalidHandleFunction; */ public final class SaFirewallStrategy { - private SaFirewallStrategy() { - } - /** * 全局单例引用 */ @@ -38,76 +42,38 @@ public final class SaFirewallStrategy { // ----------------------- 所有策略 + public List- * SaFirewallStrategy.instance.requestPathInvalidHandle = (e, extArg1, extArg2) -> { + * SaFirewallStrategy.instance.checkFailHandle = (e, req, res, extArg) -> { * // 自定义处理逻辑 ... * }; **/ - public SaRequestPathInvalidHandleFunction requestPathInvalidHandle = null; + public SaFirewallCheckFailHandleFunction checkFailHandle = null; } diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHook.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHook.java new file mode 100644 index 00000000..53e7b2ed --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHook.java @@ -0,0 +1,39 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.strategy.hooks; + +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; + +/** + * 防火墙策略校验钩子函数 - 接口 + * + * @author click33 + * @since 1.41.0 + */ +@FunctionalInterface +public interface SaFirewallCheckHook { + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 + */ + void execute(SaRequest req, SaResponse res, Object extArg); + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForBlackList.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForBlackList.java new file mode 100644 index 00000000..1be62b83 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForBlackList.java @@ -0,0 +1,58 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.strategy.hooks; + +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.exception.RequestPathInvalidException; + +/** + * 防火墙策略校验钩子函数:黑名单校验 + * + * @author click33 + * @since 1.41.0 + */ +public class SaFirewallCheckHookForBlackList implements SaFirewallCheckHook { + + /** + * 默认实例 + */ + public static SaFirewallCheckHookForBlackList instance = new SaFirewallCheckHookForBlackList(); + + /** + * 请求 path 黑名单 + */ + public String[] blackPaths = {}; + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 扩展预留参数 + */ + @Override + public void execute(SaRequest req, SaResponse res, Object extArg) { + String requestPath = req.getRequestPath(); + for (String item : blackPaths) { + if (requestPath.equals(item)) { + throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath); + } + } + + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDangerCharacter.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDangerCharacter.java new file mode 100644 index 00000000..d2fbac3e --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDangerCharacter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.strategy.hooks; + +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.exception.RequestPathInvalidException; + +/** + * 防火墙策略校验钩子函数:危险字符校验 + * + * @author click33 + * @since 1.41.0 + */ +public class SaFirewallCheckHookForDangerCharacter implements SaFirewallCheckHook { + + /** + * 默认实例 + */ + public static SaFirewallCheckHookForDangerCharacter instance = new SaFirewallCheckHookForDangerCharacter(); + + /** + * 请求 path 不允许出现的危险字符 + */ + public String[] dangerCharacter = { + "//", // // + "\\", // \ + "%2e", "%2E", // . + "%2f", "%2F", // / + "%5c", "%5C", // \ + ";", "%3b", "%3B", // ; // 参考资料:https://mp.weixin.qq.com/s/77CIDZbgBwRunJeluofPTA + "%25", // 空格 + "/.", "\\.", // /. \. 目录遍历符 + }; + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 + */ + @Override + public void execute(SaRequest req, SaResponse res, Object extArg) { + String requestPath = req.getRequestPath(); + for (String item : dangerCharacter) { + if (requestPath.contains(item)) { + throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath); + } + } + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForWhiteList.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForWhiteList.java new file mode 100644 index 00000000..bfd08d13 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForWhiteList.java @@ -0,0 +1,58 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.strategy.hooks; + +import cn.dev33.satoken.context.model.SaRequest; +import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.exception.StopMatchException; + +/** + * 防火墙策略校验钩子函数:白名单放行 + * + * @author click33 + * @since 1.41.0 + */ +public class SaFirewallCheckHookForWhiteList implements SaFirewallCheckHook { + + /** + * 默认实例 + */ + public static SaFirewallCheckHookForWhiteList instance = new SaFirewallCheckHookForWhiteList(); + + /** + * 请求 path 白名单 + */ + public String[] whitePaths = {}; + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 + */ + @Override + public void execute(SaRequest req, SaResponse res, Object extArg) { + String requestPath = req.getRequestPath(); + for (String item : whitePaths) { + if (requestPath.equals(item)) { + throw new StopMatchException(); + } + } + + } + +} diff --git a/sa-token-demo/sa-token-demo-test/pom.xml b/sa-token-demo/sa-token-demo-test/pom.xml index f310d333..64ff9c72 100644 --- a/sa-token-demo/sa-token-demo-test/pom.xml +++ b/sa-token-demo/sa-token-demo-test/pom.xml @@ -60,11 +60,6 @@