mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-11 05:19:00 +08:00
🔒 Fixing security issues. #1932 启动支持 @Inner 路径安全性检测
This commit is contained in:
1 parent
bdf0824e30
commit
7f651b4667
2 files changed
+64
-9
No files matched your search
+5
@@ -25,6 +25,11 @@ package com.pig4cloud.pigx.common.core.constant;
|
||||
*/
|
||||
public interface SecurityConstants {
|
||||
|
||||
/**
|
||||
* 启动时是否检查Inner注解安全性
|
||||
*/
|
||||
boolean INNER_CHECK = true;
|
||||
|
||||
/**
|
||||
* 刷新
|
||||
*/
|
||||
|
||||
+59
-9
@@ -21,6 +21,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pigx.common.security.annotation.Inner;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -34,7 +35,8 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
@@ -59,6 +61,8 @@ import java.util.stream.Collectors;
|
||||
@ConfigurationProperties(prefix = "security.oauth2.client")
|
||||
public class PermitAllUrlResolver implements InitializingBean {
|
||||
|
||||
private static final PathMatcher PATHMATCHER = new AntPathMatcher();
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
private final WebApplicationContext applicationContext;
|
||||
@@ -81,9 +85,8 @@ public class PermitAllUrlResolver implements InitializingBean {
|
||||
// 2. 当类上不包含 @Inner 注解则获取该方法的注解
|
||||
if (controller == null) {
|
||||
Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
|
||||
RequestMapping rq = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), RequestMapping.class);
|
||||
Optional.ofNullable(method).ifPresent(
|
||||
inner -> info.getPatternsCondition().getPatterns().forEach(url -> this.filterPath(url, rq)));
|
||||
inner -> info.getPatternsCondition().getPatterns().forEach(url -> this.filterPath(url, info, map)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -92,8 +95,7 @@ public class PermitAllUrlResolver implements InitializingBean {
|
||||
Method[] methods = beanType.getDeclaredMethods();
|
||||
Method method = handlerMethod.getMethod();
|
||||
if (ArrayUtil.contains(methods, method)) {
|
||||
RequestMapping rq = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
||||
info.getPatternsCondition().getPatterns().forEach(url -> filterPath(url, rq));
|
||||
info.getPatternsCondition().getPatterns().forEach(url -> filterPath(url, info, map));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,14 +104,21 @@ public class PermitAllUrlResolver implements InitializingBean {
|
||||
/**
|
||||
* 过滤 Inner 设置
|
||||
*
|
||||
* <p>0. 暴露安全检查</p>
|
||||
* <p>1. 路径转换: 如果为restful(/xx/{xx}) --> /xx/* ant 表达式</p>
|
||||
* <p> 2. 构建表达式:允许暴露的接口|允许暴露的方法类型,允许暴露的方法类型 URL|GET,POST,DELETE,PUT</p>
|
||||
*
|
||||
* @param url mapping路径
|
||||
* @param rq 请求犯法
|
||||
* @param url mapping路径
|
||||
* @param info 请求犯法
|
||||
* @param map 路由映射信息
|
||||
*/
|
||||
private void filterPath(String url, RequestMapping rq) {
|
||||
List<String> methodList = Arrays.stream(rq.method()).map(RequestMethod::name).collect(Collectors.toList());
|
||||
private void filterPath(String url, RequestMappingInfo info, Map<RequestMappingInfo, HandlerMethod> map) {
|
||||
// 安全检查
|
||||
if (SecurityConstants.INNER_CHECK){
|
||||
security(url, info, map);
|
||||
}
|
||||
|
||||
List<String> methodList = info.getMethodsCondition().getMethods().stream().map(RequestMethod::name).collect(Collectors.toList());
|
||||
String resultUrl = ReUtil.replaceAll(url, PATTERN, "*");
|
||||
if (CollUtil.isEmpty(methodList)) {
|
||||
ignoreUrls.add(resultUrl);
|
||||
@@ -118,6 +127,47 @@ public class PermitAllUrlResolver implements InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对Pathvariable 请求安全检查。增加启动好使影响启动效率 请注意
|
||||
*
|
||||
* @param url 接口路径
|
||||
* @param rq 当前请求的元信息
|
||||
* @param map springmvc 接口列表
|
||||
*/
|
||||
private void security(String url, RequestMappingInfo rq, Map<RequestMappingInfo, HandlerMethod> map) {
|
||||
// 判断 URL 是否是 rest path 形式
|
||||
if (!StrUtil.containsAny(url, StrUtil.DELIM_START, StrUtil.DELIM_END)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RequestMappingInfo info : map.keySet()) {
|
||||
Set<RequestMethod> methods = info.getMethodsCondition().getMethods();
|
||||
// 如果请求方法不匹配跳过
|
||||
if (!CollUtil.containsAny(methods, rq.getMethodsCondition().getMethods())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果请求方法路径匹配
|
||||
Set<String> patterns = info.getPatternsCondition().getPatterns();
|
||||
for (String pattern : patterns) {
|
||||
// 跳过自身
|
||||
if (StrUtil.equals(url, pattern)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PATHMATCHER.match(url, pattern)) {
|
||||
HandlerMethod rqMethod = map.get(rq);
|
||||
HandlerMethod infoMethod = map.get(info);
|
||||
log.error("@Inner 标记接口 ==> {}.{} 使用不当,会额外暴露接口 ==> {}.{} 请知悉"
|
||||
, rqMethod.getBeanType().getName()
|
||||
, rqMethod.getMethod().getName()
|
||||
, infoMethod.getBeanType().getName()
|
||||
, infoMethod.getMethod().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对外暴露的URL,注册到 spring security
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user