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 @@