mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 04:39:00 +08:00
refactor(common): security 增加配置项,如果设置 skipPublicUrl true 如果接口对外设置,即使携带token 也不鉴权
This commit is contained in:
1 parent
8be6f31786
commit
f738bed680
2 files changed
+100
-90
No files matched your search
+35
-22
@@ -42,33 +42,46 @@ import java.util.regex.Pattern;
|
||||
@ConfigurationProperties(prefix = "security.oauth2.client")
|
||||
public class PermitAllUrlProperties implements InitializingBean {
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
private static final String[] DEFAULT_IGNORE_URLS = new String[] { "/actuator/**", "/error", "/v3/api-docs" };
|
||||
private static final String[] DEFAULT_IGNORE_URLS = new String[]{"/actuator/**", "/error", "/v3/api-docs"};
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private List<String> ignoreUrls = new ArrayList<>();
|
||||
@Getter
|
||||
@Setter
|
||||
private List<String> ignoreUrls = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
ignoreUrls.addAll(Arrays.asList(DEFAULT_IGNORE_URLS));
|
||||
RequestMappingHandlerMapping mapping = SpringContextHolder.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
/**
|
||||
* 跳过对外 URL
|
||||
* <p>
|
||||
* 比如某个接口是对外开放的,即使携带 token,也不鉴权
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean skipPublicUrl = false;
|
||||
|
||||
map.keySet().forEach(info -> {
|
||||
HandlerMethod handlerMethod = map.get(info);
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
ignoreUrls.addAll(Arrays.asList(DEFAULT_IGNORE_URLS));
|
||||
RequestMappingHandlerMapping mapping = SpringContextHolder.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
|
||||
// 获取方法上边的注解 替代path variable 为 *
|
||||
Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
|
||||
Optional.ofNullable(method).ifPresent(inner -> Objects.requireNonNull(info.getPathPatternsCondition())
|
||||
.getPatternValues().forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, "*"))));
|
||||
map.keySet().forEach(info -> {
|
||||
HandlerMethod handlerMethod = map.get(info);
|
||||
|
||||
// 获取类上边的注解, 替代path variable 为 *
|
||||
Inner controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Inner.class);
|
||||
Optional.ofNullable(controller).ifPresent(inner -> Objects.requireNonNull(info.getPathPatternsCondition())
|
||||
.getPatternValues().forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, "*"))));
|
||||
});
|
||||
}
|
||||
// 获取方法上边的注解 替代path variable 为 *
|
||||
Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
|
||||
Optional.ofNullable(method)
|
||||
.ifPresent(inner -> Objects.requireNonNull(info.getPathPatternsCondition())
|
||||
.getPatternValues()
|
||||
.forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, "*"))));
|
||||
|
||||
// 获取类上边的注解, 替代path variable 为 *
|
||||
Inner controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Inner.class);
|
||||
Optional.ofNullable(controller)
|
||||
.ifPresent(inner -> Objects.requireNonNull(info.getPathPatternsCondition())
|
||||
.getPatternValues()
|
||||
.forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, "*"))));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
+65
-68
@@ -17,7 +17,6 @@
|
||||
package com.pig4cloud.pigx.common.security.component;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenError;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
|
||||
@@ -36,86 +35,84 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class PigxBearerTokenExtractor implements BearerTokenResolver {
|
||||
|
||||
private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?<token>[a-zA-Z0-9-:._~+/]+=*)$",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?<token>[a-zA-Z0-9-:._~+/]+=*)$",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private boolean allowFormEncodedBodyParameter = false;
|
||||
|
||||
private boolean allowUriQueryParameter = true;
|
||||
private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION;
|
||||
|
||||
private String bearerTokenHeaderName = HttpHeaders.AUTHORIZATION;
|
||||
private final PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
private final PathMatcher pathMatcher = new AntPathMatcher();
|
||||
private final PermitAllUrlProperties urlProperties;
|
||||
|
||||
private final PermitAllUrlProperties urlProperties;
|
||||
public PigxBearerTokenExtractor(PermitAllUrlProperties urlProperties) {
|
||||
this.urlProperties = urlProperties;
|
||||
}
|
||||
|
||||
public PigxBearerTokenExtractor(PermitAllUrlProperties urlProperties) {
|
||||
this.urlProperties = urlProperties;
|
||||
}
|
||||
/**
|
||||
* 解析令牌
|
||||
*
|
||||
* @param request 请求
|
||||
* @return {@link String }
|
||||
*/
|
||||
@Override
|
||||
public String resolve(HttpServletRequest request) {
|
||||
String requestUri = request.getRequestURI();
|
||||
String relativePath = requestUri.substring(request.getContextPath().length());
|
||||
|
||||
@Override
|
||||
public String resolve(HttpServletRequest request) {
|
||||
String requestUri = request.getRequestURI();
|
||||
String relativePath = requestUri.substring(request.getContextPath().length());
|
||||
if (urlProperties.isSkipPublicUrl()) {
|
||||
boolean match = urlProperties.getIgnoreUrls().stream().anyMatch(url -> pathMatcher.match(url, relativePath));
|
||||
|
||||
boolean match = urlProperties.getIgnoreUrls().stream().anyMatch(url -> pathMatcher.match(url, relativePath));
|
||||
if (match) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
||||
final String parameterToken = isParameterTokenSupportedForRequest(request)
|
||||
? resolveFromRequestParameters(request) : null;
|
||||
if (authorizationHeaderToken != null) {
|
||||
if (parameterToken != null) {
|
||||
final BearerTokenError error = BearerTokenErrors
|
||||
.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
if (parameterToken != null && isParameterTokenEnabledForRequest(request)) {
|
||||
return parameterToken;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
|
||||
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return matcher.group("token");
|
||||
}
|
||||
if (authorizationHeaderToken != null) {
|
||||
return authorizationHeaderToken;
|
||||
}
|
||||
|
||||
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
||||
String[] values = request.getParameterValues("access_token");
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (values.length == 1) {
|
||||
return values[0];
|
||||
}
|
||||
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return resolveFromRequestParameters(request);
|
||||
}
|
||||
|
||||
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
|
||||
return (("POST".equals(request.getMethod())
|
||||
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
|
||||
|| "GET".equals(request.getMethod()));
|
||||
}
|
||||
/**
|
||||
* 从授权标头解析
|
||||
*
|
||||
* @param request 请求
|
||||
* @return {@link String }
|
||||
*/
|
||||
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
|
||||
String authorization = request.getHeader(this.bearerTokenHeaderName);
|
||||
if (!StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = authorizationPattern.matcher(authorization);
|
||||
if (!matcher.matches()) {
|
||||
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
return matcher.group("token");
|
||||
}
|
||||
|
||||
private boolean isParameterTokenEnabledForRequest(final HttpServletRequest request) {
|
||||
return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod())
|
||||
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
|
||||
|| (this.allowUriQueryParameter && "GET".equals(request.getMethod())));
|
||||
}
|
||||
/**
|
||||
* 从请求参数解析
|
||||
*
|
||||
* @param request 请求
|
||||
* @return {@link String }
|
||||
*/
|
||||
private static String resolveFromRequestParameters(HttpServletRequest request) {
|
||||
String[] values = request.getParameterValues("access_token");
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (values.length == 1) {
|
||||
return values[0];
|
||||
}
|
||||
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user