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 b77682f8..df345c00 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 @@ -47,6 +47,7 @@ public final class SaFirewallStrategy { checkHooks.add(SaFirewallCheckHookForDangerCharacter.instance); checkHooks.add(SaFirewallCheckHookForDirectoryTraversal.instance); checkHooks.add(SaFirewallCheckHookForHost.instance); + checkHooks.add(SaFirewallCheckHookForHttpMethod.instance); } // 注册一个防火墙校验 hook 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 index 1be62b83..9679b4e5 100644 --- 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 @@ -20,7 +20,7 @@ import cn.dev33.satoken.context.model.SaResponse; import cn.dev33.satoken.exception.RequestPathInvalidException; /** - * 防火墙策略校验钩子函数:黑名单校验 + * 防火墙策略校验钩子函数:请求 path 黑名单校验 * * @author click33 * @since 1.41.0 @@ -37,6 +37,14 @@ public class SaFirewallCheckHookForBlackList implements SaFirewallCheckHook { */ public String[] blackPaths = {}; + /** + * 重载配置 + * @param paths 黑名单 path 列表 + */ + public void resetConfig(String... paths) { + this.blackPaths = paths; + } + /** * 执行的方法 * 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 index e4579438..f7850df6 100644 --- 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 @@ -20,7 +20,7 @@ import cn.dev33.satoken.context.model.SaResponse; import cn.dev33.satoken.exception.RequestPathInvalidException; /** - * 防火墙策略校验钩子函数:危险字符校验 + * 防火墙策略校验钩子函数:请求 path 危险字符校验 * * @author click33 * @since 1.41.0 @@ -45,6 +45,14 @@ public class SaFirewallCheckHookForDangerCharacter implements SaFirewallCheckHoo "%25" // 空格 }; + /** + * 重载配置 + * @param character 危险字符列表 + */ + public void resetConfig(String... character) { + this.dangerCharacter = character; + } + /** * 执行的方法 * diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java index 1825be19..483d3973 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForDirectoryTraversal.java @@ -20,7 +20,7 @@ import cn.dev33.satoken.context.model.SaResponse; import cn.dev33.satoken.exception.RequestPathInvalidException; /** - * 防火墙策略校验钩子函数:目录遍历符检测 + * 防火墙策略校验钩子函数:请求 path 目录遍历符检测 * * @author click33 * @since 1.41.0 diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java index 4123a677..61ee7a4a 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java @@ -38,9 +38,9 @@ public class SaFirewallCheckHookForHost implements SaFirewallCheckHook { public static SaFirewallCheckHookForHost instance = new SaFirewallCheckHookForHost(); /** - * 是否校验 host + * 是否校验 host,默认关闭 */ - public Boolean isCheckHost = false; + public boolean isCheckHost = false; /** * 允许的 host 列表,允许通配符 @@ -48,12 +48,13 @@ public class SaFirewallCheckHookForHost implements SaFirewallCheckHook { public List allowHosts = new ArrayList<>(); /** - * 配置 + * 重载配置 * @param isCheckHost 是否校验 host - * @param allowHosts 允许的 host 列表 + * @param allowHosts 允许的 host 列表 (先清空原来的,再添加上新的) */ - public void config(Boolean isCheckHost, String... allowHosts) { + public void resetConfig(boolean isCheckHost, String... allowHosts) { this.isCheckHost = isCheckHost; + this.allowHosts.clear(); this.allowHosts.addAll(Arrays.asList(allowHosts)); } diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHttpMethod.java b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHttpMethod.java new file mode 100644 index 00000000..f3162150 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHttpMethod.java @@ -0,0 +1,91 @@ +/* + * 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.FirewallCheckException; +import cn.dev33.satoken.router.SaHttpMethod; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 防火墙策略校验钩子函数:请求 Method 检测 + * + * @author click33 + * @since 1.41.0 + */ +public class SaFirewallCheckHookForHttpMethod implements SaFirewallCheckHook { + + /** + * 默认实例 + */ + public static SaFirewallCheckHookForHttpMethod instance = new SaFirewallCheckHookForHttpMethod(); + + /** + * 是否校验 请求Method,默认开启 + */ + public boolean isCheckMethod = true; + + /** + * 允许的 HttpMethod 列表 + */ + public List allowMethods = new ArrayList<>(); + + public SaFirewallCheckHookForHttpMethod() { + // 默认允许的 HttpMethod 列表 + allowMethods.add(SaHttpMethod.GET.name()); + allowMethods.add(SaHttpMethod.POST.name()); + allowMethods.add(SaHttpMethod.PUT.name()); + allowMethods.add(SaHttpMethod.DELETE.name()); + allowMethods.add(SaHttpMethod.HEAD.name()); + allowMethods.add(SaHttpMethod.OPTIONS.name()); + allowMethods.add(SaHttpMethod.PATCH.name()); + allowMethods.add(SaHttpMethod.TRACE.name()); + allowMethods.add(SaHttpMethod.CONNECT.name()); + } + + /** + * 配置 + * @param isCheckMethod 是否校验 Method + * @param methods 允许的 HttpMethod 列表 (先清空原来的,再添加上新的) + */ + public void resetConfig(boolean isCheckMethod, String... methods) { + this.isCheckMethod = isCheckMethod; + this.allowMethods.clear(); + this.allowMethods.addAll(Arrays.asList(methods)); + } + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 + */ + @Override + public void execute(SaRequest req, SaResponse res, Object extArg) { + if(isCheckMethod) { + String method = req.getMethod(); + if( ! allowMethods.contains(method) ) { + throw new FirewallCheckException("非法请求 Method:" + method); + } + } + } + +} 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 index bfd08d13..d7e45c99 100644 --- 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 @@ -20,7 +20,7 @@ import cn.dev33.satoken.context.model.SaResponse; import cn.dev33.satoken.exception.StopMatchException; /** - * 防火墙策略校验钩子函数:白名单放行 + * 防火墙策略校验钩子函数:请求 path 白名单放行 * * @author click33 * @since 1.41.0 @@ -37,6 +37,14 @@ public class SaFirewallCheckHookForWhiteList implements SaFirewallCheckHook { */ public String[] whitePaths = {}; + /** + * 重载配置 + * @param paths 白名单 path 列表 + */ + public void resetConfig(String... paths) { + this.whitePaths = paths; + } + /** * 执行的方法 * diff --git a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java index f2cd3cb1..c6d0632a 100644 --- a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java @@ -1,12 +1,5 @@ package com.pj.test; -import java.util.Date; -import java.util.List; - -import cn.dev33.satoken.context.SaHolder; -import com.pj.util.AjaxJson; -import com.pj.util.Ttime; - import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckRole; @@ -14,11 +7,16 @@ import cn.dev33.satoken.annotation.SaMode; import cn.dev33.satoken.session.SaSessionCustomUtil; import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; +import com.pj.util.AjaxJson; +import com.pj.util.Ttime; import org.noear.snack.ONode; import org.noear.solon.annotation.Controller; import org.noear.solon.annotation.Mapping; import org.noear.solon.annotation.Param; +import java.util.Date; +import java.util.List; + /** * 测试专用Controller * @author click33 @@ -246,7 +244,6 @@ public class TestController { // 测试 浏览器访问: http://localhost:8081/test/test2 @Mapping("test2") public AjaxJson test2() { - System.out.println(SaHolder.getRequest().getHost()); return AjaxJson.getSuccess(); }