mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-07 23:24:24 +08:00
refactor: 重构防火墙模块,增加 hooks 机制
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -21,7 +21,7 @@ package cn.dev33.satoken.exception;
|
|||||||
* @author click33
|
* @author click33
|
||||||
* @since 1.37.0
|
* @since 1.37.0
|
||||||
*/
|
*/
|
||||||
public class RequestPathInvalidException extends SaTokenException {
|
public class RequestPathInvalidException extends FirewallCheckException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化版本号
|
* 序列化版本号
|
||||||
|
@@ -15,25 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.fun.strategy;
|
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 的算法
|
* 函数式接口:当防火墙校验不通过时执行的函数
|
||||||
*
|
|
||||||
* <p> 如果属于无效请求 path,则抛出异常 RequestPathInvalidException </p>
|
|
||||||
*
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
* @since 1.37.0
|
* @since 1.37.0
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface SaCheckRequestPathFunction {
|
public interface SaFirewallCheckFailHandleFunction {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行函数
|
* 执行函数
|
||||||
* @param path 请求 path
|
* @param e 防火墙校验异常
|
||||||
* @param extArg1 扩展参数1
|
* @param req 请求对象
|
||||||
* @param extArg2 扩展参数2
|
* @param res 响应对象
|
||||||
|
* @param extArg 预留扩展参数
|
||||||
*/
|
*/
|
||||||
void run(String path, Object extArg1, Object extArg2);
|
void run(FirewallCheckException e, SaRequest req, SaResponse res, Object extArg);
|
||||||
|
|
||||||
}
|
}
|
@@ -15,23 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.fun.strategy;
|
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
|
* @author click33
|
||||||
* @since 1.37.0
|
* @since 1.37.0
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface SaRequestPathInvalidHandleFunction {
|
public interface SaFirewallCheckFunction {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行函数
|
* 执行函数
|
||||||
* @param e 请求 path 无效的异常对象
|
*
|
||||||
* @param extArg1 扩展参数1
|
* @param req 请求对象
|
||||||
* @param extArg2 扩展参数2
|
* @param res 响应对象
|
||||||
|
* @param extArg 预留扩展参数
|
||||||
*/
|
*/
|
||||||
void run(RequestPathInvalidException e, Object extArg1, Object extArg2);
|
void execute(SaRequest req, SaResponse res, Object extArg);
|
||||||
|
|
||||||
}
|
}
|
@@ -15,9 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.strategy;
|
package cn.dev33.satoken.strategy;
|
||||||
|
|
||||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.fun.strategy.SaCheckRequestPathFunction;
|
import cn.dev33.satoken.fun.strategy.SaFirewallCheckFailHandleFunction;
|
||||||
import cn.dev33.satoken.fun.strategy.SaRequestPathInvalidHandleFunction;
|
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 防火墙策略
|
* Sa-Token 防火墙策略
|
||||||
@@ -27,9 +34,6 @@ import cn.dev33.satoken.fun.strategy.SaRequestPathInvalidHandleFunction;
|
|||||||
*/
|
*/
|
||||||
public final class SaFirewallStrategy {
|
public final class SaFirewallStrategy {
|
||||||
|
|
||||||
private SaFirewallStrategy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局单例引用
|
* 全局单例引用
|
||||||
*/
|
*/
|
||||||
@@ -38,76 +42,38 @@ public final class SaFirewallStrategy {
|
|||||||
|
|
||||||
// ----------------------- 所有策略
|
// ----------------------- 所有策略
|
||||||
|
|
||||||
|
public List<SaFirewallCheckHook> checkHooks = new ArrayList<>();
|
||||||
|
|
||||||
|
private SaFirewallStrategy() {
|
||||||
|
checkHooks.add(SaFirewallCheckHookForWhiteList.instance);
|
||||||
|
checkHooks.add(SaFirewallCheckHookForBlackList.instance);
|
||||||
|
checkHooks.add(SaFirewallCheckHookForDangerCharacter.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册一个防火墙校验 hook
|
||||||
|
public void registerCheckHook(SaFirewallCheckHook checkHook) {
|
||||||
|
SaManager.getLog().info("防火墙校验 hook 注册成功: " + checkHook.getClass());
|
||||||
|
checkHooks.add(checkHook);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求 path 黑名单
|
* 防火墙校验函数
|
||||||
*/
|
*/
|
||||||
public String[] blackPaths = {};
|
public SaFirewallCheckFunction check = (req, res, extArg) -> {
|
||||||
|
for (SaFirewallCheckHook checkHook : checkHooks) {
|
||||||
/**
|
checkHook.execute(req, res, extArg);
|
||||||
* 请求 path 白名单
|
}
|
||||||
*/
|
|
||||||
public String[] whitePaths = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求 path 不允许出现的字符
|
|
||||||
*/
|
|
||||||
public String[] invalidCharacter = {
|
|
||||||
"//", // //
|
|
||||||
"\\", // \
|
|
||||||
"%2e", "%2E", // .
|
|
||||||
"%2f", "%2F", // /
|
|
||||||
"%5c", "%5C", // \
|
|
||||||
";", "%3b", "%3B", // ; // 参考资料:https://mp.weixin.qq.com/s/77CIDZbgBwRunJeluofPTA
|
|
||||||
"%25" // 空格
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验请求 path 的算法
|
* 当请求 path 校验不通过时地处理方案,自定义示例:
|
||||||
*/
|
|
||||||
public SaCheckRequestPathFunction checkRequestPath = (requestPath, extArg1, extArg2) -> {
|
|
||||||
// 1、如果在白名单里,则直接放行
|
|
||||||
for (String item : whitePaths) {
|
|
||||||
if (requestPath.equals(item)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、如果在黑名单里,则抛出异常
|
|
||||||
for (String item : blackPaths) {
|
|
||||||
if (requestPath.equals(item)) {
|
|
||||||
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3、检查是否包含非法字符
|
|
||||||
|
|
||||||
// 不允许为null
|
|
||||||
if(requestPath == null) {
|
|
||||||
throw new RequestPathInvalidException("非法请求:null", null);
|
|
||||||
}
|
|
||||||
// 不允许包含非法字符
|
|
||||||
for (String item : invalidCharacter) {
|
|
||||||
if (requestPath.contains(item)) {
|
|
||||||
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 不允许出现跨目录字符
|
|
||||||
if(requestPath.contains("/.") || requestPath.contains("\\.")) {
|
|
||||||
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当请求 path 校验不通过时处理方案的算法,自定义示例:
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* SaFirewallStrategy.instance.requestPathInvalidHandle = (e, extArg1, extArg2) -> {
|
* SaFirewallStrategy.instance.checkFailHandle = (e, req, res, extArg) -> {
|
||||||
* // 自定义处理逻辑 ...
|
* // 自定义处理逻辑 ...
|
||||||
* };
|
* };
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public SaRequestPathInvalidHandleFunction requestPathInvalidHandle = null;
|
public SaFirewallCheckFailHandleFunction checkFailHandle = null;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
}
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -60,11 +60,6 @@
|
|||||||
<artifactId>sa-token-redis-template</artifactId>
|
<artifactId>sa-token-redis-template</artifactId>
|
||||||
<version>${sa-token.version}</version>
|
<version>${sa-token.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>cn.dev33</groupId>
|
|
||||||
<artifactId>sa-token-fastjson2</artifactId>
|
|
||||||
<version>${sa-token.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 提供Redis连接池 -->
|
<!-- 提供Redis连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -38,13 +38,13 @@ public class SaPathCheckFilterForReactor implements WebFilter {
|
|||||||
|
|
||||||
// 校验本次请求 path 是否合法
|
// 校验本次请求 path 是否合法
|
||||||
try {
|
try {
|
||||||
SaFirewallStrategy.instance.checkRequestPath.run(exchange.getRequest().getPath().toString(), exchange, null);
|
SaFirewallStrategy.instance.check.run(exchange.getRequest().getPath().toString(), exchange, null);
|
||||||
} catch (RequestPathInvalidException e) {
|
} catch (RequestPathInvalidException e) {
|
||||||
if(SaFirewallStrategy.instance.requestPathInvalidHandle == null) {
|
if(SaFirewallStrategy.instance.checkFailHandle == null) {
|
||||||
exchange.getResponse().getHeaders().set(SaTokenConsts.CONTENT_TYPE_KEY, SaTokenConsts.CONTENT_TYPE_TEXT_PLAIN);
|
exchange.getResponse().getHeaders().set(SaTokenConsts.CONTENT_TYPE_KEY, SaTokenConsts.CONTENT_TYPE_TEXT_PLAIN);
|
||||||
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(e.getMessage().getBytes())));
|
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(e.getMessage().getBytes())));
|
||||||
} else {
|
} else {
|
||||||
SaFirewallStrategy.instance.requestPathInvalidHandle.run(e, exchange, null);
|
SaFirewallStrategy.instance.checkFailHandle.run(e, exchange, null);
|
||||||
}
|
}
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
@@ -38,13 +38,13 @@ public class SaPathCheckFilterForReactor implements WebFilter {
|
|||||||
|
|
||||||
// 校验本次请求 path 是否合法
|
// 校验本次请求 path 是否合法
|
||||||
try {
|
try {
|
||||||
SaFirewallStrategy.instance.checkRequestPath.run(exchange.getRequest().getPath().toString(), exchange, null);
|
SaFirewallStrategy.instance.check.run(exchange.getRequest().getPath().toString(), exchange, null);
|
||||||
} catch (RequestPathInvalidException e) {
|
} catch (RequestPathInvalidException e) {
|
||||||
if(SaFirewallStrategy.instance.requestPathInvalidHandle == null) {
|
if(SaFirewallStrategy.instance.checkFailHandle == null) {
|
||||||
exchange.getResponse().getHeaders().set(SaTokenConsts.CONTENT_TYPE_KEY, SaTokenConsts.CONTENT_TYPE_TEXT_PLAIN);
|
exchange.getResponse().getHeaders().set(SaTokenConsts.CONTENT_TYPE_KEY, SaTokenConsts.CONTENT_TYPE_TEXT_PLAIN);
|
||||||
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(e.getMessage().getBytes())));
|
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(e.getMessage().getBytes())));
|
||||||
} else {
|
} else {
|
||||||
SaFirewallStrategy.instance.requestPathInvalidHandle.run(e, exchange, null);
|
SaFirewallStrategy.instance.checkFailHandle.run(e, exchange, null);
|
||||||
}
|
}
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
}
|
}
|
||||||
|
@@ -15,43 +15,56 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.filter;
|
package cn.dev33.satoken.filter;
|
||||||
|
|
||||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
import cn.dev33.satoken.exception.FirewallCheckException;
|
||||||
|
import cn.dev33.satoken.exception.StopMatchException;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
|
||||||
|
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
|
||||||
import cn.dev33.satoken.strategy.SaFirewallStrategy;
|
import cn.dev33.satoken.strategy.SaFirewallStrategy;
|
||||||
import cn.dev33.satoken.util.SaTokenConsts;
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
import javax.servlet.*;
|
import javax.servlet.*;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验请求 path 是否合法
|
* 防火墙校验过滤器
|
||||||
*
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
* @since 1.37.0
|
* @since 1.37.0
|
||||||
*/
|
*/
|
||||||
@Order(SaTokenConsts.PATH_CHECK_FILTER_ORDER)
|
@Order(SaTokenConsts.PATH_CHECK_FILTER_ORDER)
|
||||||
public class SaPathCheckFilterForServlet implements Filter {
|
public class SaFirewallCheckFilterForServlet implements Filter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
|
||||||
// 校验本次请求 path 是否合法
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse res = (HttpServletResponse) response;
|
||||||
|
SaRequestForServlet saRequest = new SaRequestForServlet(req);
|
||||||
|
SaResponseForServlet saResponse = new SaResponseForServlet(res);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpServletRequest req = (HttpServletRequest) request;
|
SaFirewallStrategy.instance.check.execute(saRequest, saResponse, null);
|
||||||
SaFirewallStrategy.instance.checkRequestPath.run(req.getRequestURI(), request, response);
|
}
|
||||||
} catch (RequestPathInvalidException e) {
|
catch (StopMatchException e) {
|
||||||
if(SaFirewallStrategy.instance.requestPathInvalidHandle == null) {
|
// 如果是 StopMatchException 异常,代表通过了防火墙验证,进入 Controller
|
||||||
|
}
|
||||||
|
catch (FirewallCheckException e) {
|
||||||
|
// FirewallCheckException 异常则交由异常处理策略处理
|
||||||
|
if(SaFirewallStrategy.instance.checkFailHandle == null) {
|
||||||
response.setContentType("text/plain; charset=utf-8");
|
response.setContentType("text/plain; charset=utf-8");
|
||||||
response.getWriter().print(e.getMessage());
|
response.getWriter().print(e.getMessage());
|
||||||
response.getWriter().flush();
|
response.getWriter().flush();
|
||||||
} else {
|
} else {
|
||||||
SaFirewallStrategy.instance.requestPathInvalidHandle.run(e, request, response);
|
SaFirewallStrategy.instance.checkFailHandle.run(e, saRequest, saResponse, null);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 更多异常则不处理,交由 Web 框架处理
|
||||||
|
|
||||||
// 向下执行
|
// 向内执行
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
@@ -16,7 +16,7 @@
|
|||||||
package cn.dev33.satoken.spring;
|
package cn.dev33.satoken.spring;
|
||||||
|
|
||||||
import cn.dev33.satoken.context.SaTokenContext;
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
import cn.dev33.satoken.filter.SaPathCheckFilterForServlet;
|
import cn.dev33.satoken.filter.SaFirewallCheckFilterForServlet;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,8 +43,8 @@ public class SaTokenContextRegister {
|
|||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public SaPathCheckFilterForServlet saPathCheckFilterForServlet() {
|
public SaFirewallCheckFilterForServlet saPathCheckFilterForServlet() {
|
||||||
return new SaPathCheckFilterForServlet();
|
return new SaFirewallCheckFilterForServlet();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -39,14 +39,14 @@ public class SaPathCheckFilterForJakartaServlet implements Filter {
|
|||||||
// 校验本次请求 path 是否合法
|
// 校验本次请求 path 是否合法
|
||||||
try {
|
try {
|
||||||
HttpServletRequest req = (HttpServletRequest) request;
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
SaFirewallStrategy.instance.checkRequestPath.run(req.getRequestURI(), request, response);
|
SaFirewallStrategy.instance.check.run(req.getRequestURI(), request, response);
|
||||||
} catch (RequestPathInvalidException e) {
|
} catch (RequestPathInvalidException e) {
|
||||||
if(SaFirewallStrategy.instance.requestPathInvalidHandle == null) {
|
if(SaFirewallStrategy.instance.checkFailHandle == null) {
|
||||||
response.setContentType("text/plain; charset=utf-8");
|
response.setContentType("text/plain; charset=utf-8");
|
||||||
response.getWriter().print(e.getMessage());
|
response.getWriter().print(e.getMessage());
|
||||||
response.getWriter().flush();
|
response.getWriter().flush();
|
||||||
} else {
|
} else {
|
||||||
SaFirewallStrategy.instance.requestPathInvalidHandle.run(e, request, response);
|
SaFirewallStrategy.instance.checkFailHandle.run(e, request, response);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user