Skip to content

Commit 954efeb

Browse files
committed
修复路由拦截鉴权可被绕过的问题 fix #515
1 parent f2416a6 commit 954efeb

33 files changed

Lines changed: 688 additions & 79 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2020-2099 sa-token.cc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package cn.dev33.satoken.application;
17+
18+
import cn.dev33.satoken.util.SaFoxUtil;
19+
20+
/**
21+
* 应用全局信息
22+
*
23+
* @author click33
24+
* @since 1.31.0
25+
*/
26+
public class ApplicationInfo {
27+
28+
/**
29+
* 应用前缀
30+
*/
31+
public static String routePrefix;
32+
33+
/**
34+
* 为指定 path 裁剪掉 routePrefix 前缀
35+
* @param path 指定 path
36+
* @return /
37+
*/
38+
public static String cutPathPrefix(String path) {
39+
if(! SaFoxUtil.isEmpty(routePrefix) && ! routePrefix.equals("/") && path.startsWith(routePrefix)){
40+
path = path.substring(routePrefix.length());
41+
}
42+
return path;
43+
}
44+
45+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2020-2099 sa-token.cc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package cn.dev33.satoken.exception;
17+
18+
/**
19+
* 一个异常:代表请求 path 无效或非法
20+
*
21+
* @author click33
22+
* @since 1.37.0
23+
*/
24+
public class RequestPathInvalidException extends SaTokenException {
25+
26+
/**
27+
* 序列化版本号
28+
*/
29+
private static final long serialVersionUID = 8243974276159004739L;
30+
31+
/** 具体无效的 path */
32+
private final String path;
33+
34+
/**
35+
* @return 具体无效的 path
36+
*/
37+
public String getPath() {
38+
return path;
39+
}
40+
41+
public RequestPathInvalidException(String message, String path) {
42+
super(message);
43+
this.path = path;
44+
}
45+
46+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2020-2099 sa-token.cc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package cn.dev33.satoken.fun.strategy;
17+
18+
import cn.dev33.satoken.exception.RequestPathInvalidException;
19+
20+
/**
21+
* 函数式接口:校验请求 path 的算法
22+
*
23+
* <p> 如果属于无效请求 path,则抛出异常 RequestPathInvalidException </p>
24+
*
25+
* @author click33
26+
* @since 1.37.0
27+
*/
28+
@FunctionalInterface
29+
public interface SaCheckRequestPathFunction {
30+
31+
/**
32+
* 执行函数
33+
* @param path 请求 path
34+
* @param extArg1 扩展参数1
35+
* @param extArg2 扩展参数2
36+
*/
37+
void run(String path, Object extArg1, Object extArg2);
38+
39+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2020-2099 sa-token.cc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package cn.dev33.satoken.fun.strategy;
17+
18+
import cn.dev33.satoken.exception.RequestPathInvalidException;
19+
20+
/**
21+
* 函数式接口:当请求 path 校验不通过时处理方案的算法
22+
*
23+
* @author click33
24+
* @since 1.37.0
25+
*/
26+
@FunctionalInterface
27+
public interface SaRequestPathInvalidHandleFunction {
28+
29+
/**
30+
* 执行函数
31+
* @param e 请求 path 无效的异常对象
32+
* @param extArg1 扩展参数1
33+
* @param extArg2 扩展参数2
34+
*/
35+
void run(RequestPathInvalidException e, Object extArg1, Object extArg2);
36+
37+
}

sa-token-core/src/main/java/cn/dev33/satoken/strategy/SaStrategy.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import cn.dev33.satoken.SaManager;
1919
import cn.dev33.satoken.annotation.*;
2020
import cn.dev33.satoken.basic.SaBasicUtil;
21+
import cn.dev33.satoken.exception.RequestPathInvalidException;
2122
import cn.dev33.satoken.exception.SaTokenException;
2223
import cn.dev33.satoken.fun.strategy.*;
2324
import cn.dev33.satoken.session.SaSession;
@@ -329,6 +330,49 @@ private SaStrategy() {
329330
return new StpLogic(loginType);
330331
};
331332

333+
/**
334+
* 请求 path 不允许出现的字符
335+
*/
336+
public static String[] INVALID_CHARACTER = {
337+
"//", "\\",
338+
"%2e", "%2E", // .
339+
"%2f", "%2F", // /
340+
"%5c", "%5C", // \
341+
"%25" // 空格
342+
};
343+
344+
/**
345+
* 校验请求 path 的算法
346+
*/
347+
public SaCheckRequestPathFunction checkRequestPath = (requestPath, extArg1, extArg2) -> {
348+
349+
// 不允许为null
350+
if(requestPath == null) {
351+
throw new RequestPathInvalidException("非法请求:null", null);
352+
}
353+
// 不允许包含非法字符
354+
for (String item : INVALID_CHARACTER) {
355+
if (requestPath.contains(item)) {
356+
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
357+
}
358+
}
359+
// 不允许出现跨目录
360+
if(requestPath.contains("/.") || requestPath.contains("\\.")) {
361+
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
362+
}
363+
};
364+
365+
366+
/**
367+
* 当请求 path 校验不通过时处理方案的算法,自定义示例:
368+
* <pre>
369+
* SaStrategy.instance.requestPathInvalidHandle = (e, extArg1, extArg2) -> {
370+
* // 自定义处理逻辑 ...
371+
* };
372+
* </pre>
373+
*/
374+
public SaRequestPathInvalidHandleFunction requestPathInvalidHandle = null;
375+
332376

333377
// ----------------------- 重写策略 set连缀风格
334378

sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,28 @@ private SaTokenConsts() {
186186
*/
187187
public static final int ASSEMBLY_ORDER = -100;
188188

189+
/**
190+
* 请求 path 校验过滤器的注册顺序
191+
*/
192+
public static final int PATH_CHECK_FILTER_ORDER = -1000;
193+
194+
/**
195+
* Content-Type key
196+
*/
197+
public static final String CONTENT_TYPE_KEY = "Content-Type";
198+
199+
/**
200+
* Content-Type text/plain; charset=utf-8
201+
*/
202+
public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain; charset=utf-8";
203+
204+
/**
205+
* Content-Type application/json;charset=UTF-8
206+
*/
207+
public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json;charset=UTF-8";
208+
209+
210+
189211

190212
// =================== 废弃 ===================
191213

sa-token-demo/sa-token-demo-springboot3-redis/src/main/java/com/pj/test/TestController.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.pj.test;
22

3+
import cn.dev33.satoken.context.SaHolder;
4+
import cn.dev33.satoken.spring.SpringMVCUtil;
5+
import cn.dev33.satoken.util.SaResult;
36
import org.springframework.web.bind.annotation.RequestMapping;
47
import org.springframework.web.bind.annotation.RestController;
58

6-
import cn.dev33.satoken.util.SaResult;
7-
89
/**
910
* 测试专用Controller
1011
* @author click33
@@ -27,4 +28,13 @@ public SaResult test2() {
2728
return SaResult.ok();
2829
}
2930

31+
// 测试 浏览器访问: http://localhost:8081/test/getRequestPath
32+
@RequestMapping("getRequestPath")
33+
public SaResult getRequestPath() {
34+
System.out.println("-------------- 测试请求 path 获取");
35+
System.out.println("request.getRequestURI() " + SpringMVCUtil.getRequest().getRequestURI());
36+
System.out.println("saRequest.getRequestPath() " + SaHolder.getRequest().getRequestPath());
37+
return SaResult.ok();
38+
}
39+
3040
}

sa-token-demo/sa-token-demo-springboot3-redis/src/main/resources/application.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ sa-token:
1919
# 是否输出操作日志
2020
is-log: true
2121

22-
spring:
22+
spring:
2323
data:
2424
# redis配置
2525
redis:

sa-token-demo/sa-token-demo-test/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<groupId>org.springframework.boot</groupId>
1212
<artifactId>spring-boot-starter-parent</artifactId>
1313
<version>2.5.14</version>
14+
<!--<version>2.3.0.RELEASE</version>-->
1415
<!-- <version>1.5.9.RELEASE</version> -->
1516
<relativePath/>
1617
</parent>

sa-token-demo/sa-token-demo-test/src/main/java/com/pj/current/NotFoundHandle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ public Object error(HttpServletRequest request, HttpServletResponse response) th
2323
response.setStatus(200);
2424
return SaResult.get(404, "not found", null);
2525
}
26-
26+
2727
}

0 commit comments

Comments
 (0)