diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java b/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java index 1971726d..851d70d3 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/context/model/SaRequest.java @@ -21,7 +21,6 @@ import cn.dev33.satoken.router.SaHttpMethod; import cn.dev33.satoken.util.SaFoxUtil; import java.util.Collection; -import java.util.List; import java.util.Map; /** @@ -191,6 +190,12 @@ public interface SaRequest { return getMethod().equals(method.name()); } + /** + * 查询请求 host + * @return / + */ + String getHost(); + /** * 判断此请求是否为 Ajax 异步请求 * @return / 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 49935b5d..b77682f8 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 @@ -46,6 +46,7 @@ public final class SaFirewallStrategy { checkHooks.add(SaFirewallCheckHookForBlackList.instance); checkHooks.add(SaFirewallCheckHookForDangerCharacter.instance); checkHooks.add(SaFirewallCheckHookForDirectoryTraversal.instance); + checkHooks.add(SaFirewallCheckHookForHost.instance); } // 注册一个防火墙校验 hook 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 new file mode 100644 index 00000000..4123a677 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/strategy/hooks/SaFirewallCheckHookForHost.java @@ -0,0 +1,77 @@ +/* + * 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.strategy.SaStrategy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 防火墙策略校验钩子函数:Host 检测 + * + * @author click33 + * @since 1.41.0 + */ +public class SaFirewallCheckHookForHost implements SaFirewallCheckHook { + + /** + * 默认实例 + */ + public static SaFirewallCheckHookForHost instance = new SaFirewallCheckHookForHost(); + + /** + * 是否校验 host + */ + public Boolean isCheckHost = false; + + /** + * 允许的 host 列表,允许通配符 + */ + public List allowHosts = new ArrayList<>(); + + /** + * 配置 + * @param isCheckHost 是否校验 host + * @param allowHosts 允许的 host 列表 + */ + public void config(Boolean isCheckHost, String... allowHosts) { + this.isCheckHost = isCheckHost; + this.allowHosts.addAll(Arrays.asList(allowHosts)); + } + + /** + * 执行的方法 + * + * @param req 请求对象 + * @param res 响应对象 + * @param extArg 预留扩展参数 + */ + @Override + public void execute(SaRequest req, SaResponse res, Object extArg) { + if(isCheckHost) { + String host = req.getHost(); + if( ! SaStrategy.instance.hasElement.apply(allowHosts, host) ) { + throw new FirewallCheckException("非法请求 host:" + host); + } + } + } + +} 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 30f06694..f2cd3cb1 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 @@ -3,6 +3,7 @@ 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; @@ -245,6 +246,7 @@ public class TestController { // 测试 浏览器访问: http://localhost:8081/test/test2 @Mapping("test2") public AjaxJson test2() { + System.out.println(SaHolder.getRequest().getHost()); return AjaxJson.getSuccess(); } diff --git a/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/TestController.java index e3d4ea72..3fb51c28 100644 --- a/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/TestController.java @@ -1,17 +1,15 @@ package com.pj.test; -import java.time.Duration; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.pj.util.AjaxJson; - import cn.dev33.satoken.reactor.context.SaReactorHolder; import cn.dev33.satoken.stp.StpUtil; +import com.pj.util.AjaxJson; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; +import java.time.Duration; + /** * 测试专用Controller * @author click33 diff --git a/sa-token-plugin/sa-token-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/model/SaRequestForDubbo.java b/sa-token-plugin/sa-token-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/model/SaRequestForDubbo.java index d4af48ee..9714c033 100644 --- a/sa-token-plugin/sa-token-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/model/SaRequestForDubbo.java +++ b/sa-token-plugin/sa-token-dubbo/src/main/java/cn/dev33/satoken/context/dubbo/model/SaRequestForDubbo.java @@ -143,6 +143,11 @@ public class SaRequestForDubbo implements SaRequest { return null; } + @Override + public String getHost() { + return null; + } + /** * 转发请求 */ diff --git a/sa-token-plugin/sa-token-dubbo3/src/main/java/cn/dev33/satoken/context/dubbo3/model/SaRequestForDubbo3.java b/sa-token-plugin/sa-token-dubbo3/src/main/java/cn/dev33/satoken/context/dubbo3/model/SaRequestForDubbo3.java index 036fb839..7e1c0575 100644 --- a/sa-token-plugin/sa-token-dubbo3/src/main/java/cn/dev33/satoken/context/dubbo3/model/SaRequestForDubbo3.java +++ b/sa-token-plugin/sa-token-dubbo3/src/main/java/cn/dev33/satoken/context/dubbo3/model/SaRequestForDubbo3.java @@ -143,6 +143,11 @@ public class SaRequestForDubbo3 implements SaRequest { return null; } + @Override + public String getHost() { + return null; + } + /** * 转发请求 */ diff --git a/sa-token-plugin/sa-token-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java b/sa-token-plugin/sa-token-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java index c8ab9e78..1d31617f 100644 --- a/sa-token-plugin/sa-token-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java +++ b/sa-token-plugin/sa-token-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java @@ -131,6 +131,11 @@ public class SaRequestForGrpc implements SaRequest { return null; } + @Override + public String getHost() { + return null; + } + /** * 转发请求 */ diff --git a/sa-token-starter/sa-token-jakarta-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java b/sa-token-starter/sa-token-jakarta-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java index 493fb067..ca6250a3 100644 --- a/sa-token-starter/sa-token-jakarta-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java +++ b/sa-token-starter/sa-token-jakarta-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java @@ -27,7 +27,10 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; /** * 对 SaRequest 包装类的实现(Jakarta-Servlet 版) @@ -171,6 +174,14 @@ public class SaRequestForServlet implements SaRequest { return request.getMethod(); } + /** + * 查询请求 host + */ + @Override + public String getHost() { + return request.getServerName(); + } + /** * 转发请求 */ diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java index 6280a27e..98b4c6ea 100644 --- a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java +++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java @@ -27,7 +27,8 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; -import java.util.*; +import java.util.Collection; +import java.util.Map; /** * 对 SaRequest 包装类的实现(Reactor 响应式编程版) @@ -170,6 +171,14 @@ public class SaRequestForReactor implements SaRequest { return request.getMethod().name(); } + /** + * 查询请求 host + */ + @Override + public String getHost() { + return request.getURI().getHost(); + } + /** * 转发请求 */ diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java index 65cba177..41131b6f 100644 --- a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java +++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java @@ -27,7 +27,8 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; -import java.util.*; +import java.util.Collection; +import java.util.Map; /** * 对 SaRequest 包装类的实现(Reactor 响应式编程版) @@ -170,6 +171,14 @@ public class SaRequestForReactor implements SaRequest { return request.getMethod().name(); } + /** + * 查询请求 host + */ + @Override + public String getHost() { + return request.getURI().getHost(); + } + /** * 转发请求 */ diff --git a/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java b/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java index a4023ebe..4b25c49b 100644 --- a/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java +++ b/sa-token-starter/sa-token-servlet/src/main/java/cn/dev33/satoken/servlet/model/SaRequestForServlet.java @@ -27,7 +27,10 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; /** * 对 SaRequest 包装类的实现(Servlet 版) @@ -170,6 +173,14 @@ public class SaRequestForServlet implements SaRequest { return request.getMethod(); } + /** + * 查询请求 host + */ + @Override + public String getHost() { + return request.getServerName(); + } + /** * 转发请求 */ diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java index 9f32ca6c..cc6d2ef1 100644 --- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/model/SaRequestForSolon.java @@ -20,7 +20,8 @@ import cn.dev33.satoken.context.model.SaRequest; import cn.dev33.satoken.util.SaFoxUtil; import org.noear.solon.core.handle.Context; -import java.util.*; +import java.util.Collection; +import java.util.Map; /** * @author noear @@ -107,6 +108,11 @@ public class SaRequestForSolon implements SaRequest { return ctx.method(); } + @Override + public String getHost() { + return ctx.uri().getHost(); + } + @Override public Object forward(String path) { ctx.forward(path);