diff --git a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigBearerTokenExtractor.java b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigBearerTokenExtractor.java new file mode 100644 index 00000000..db38da50 --- /dev/null +++ b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigBearerTokenExtractor.java @@ -0,0 +1,112 @@ +/* + * + * * Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com). + * *

+ * * Licensed under the GNU Lesser General Public License 3.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * *

+ * * https://www.gnu.org/licenses/lgpl.html + * *

+ * * 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 com.pig4cloud.pig.common.security.component; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; +import org.springframework.security.oauth2.provider.authentication.TokenExtractor; +import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; + +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; + +/** + * 改造 {@link BearerTokenExtractor} 对公开权限的请求不进行校验 + * + * @author caiqy + * @date 2020.05.15 + */ +@Component +public class PigBearerTokenExtractor implements TokenExtractor { + private final static Log logger = LogFactory.getLog(PigBearerTokenExtractor.class); + + private final PatternsRequestCondition patternsRequestCondition; + + public PigBearerTokenExtractor(PermitAllUrlProperties permitAllUrl) { + this.patternsRequestCondition = new PatternsRequestCondition( + permitAllUrl.getUrls().toArray(new String[0]) + ); + } + + @Override + public Authentication extract(HttpServletRequest request) { + + if (this.patternsRequestCondition.getMatchingPatterns(request.getRequestURI()).size() > 0) { + return null; + } + + String tokenValue = extractToken(request); + if (tokenValue != null) { + return new PreAuthenticatedAuthenticationToken(tokenValue, ""); + } + return null; + } + + protected String extractToken(HttpServletRequest request) { + // first check the header... + String token = extractHeaderToken(request); + + // bearer type allows a request parameter as well + if (token == null) { + logger.debug("Token not found in headers. Trying request parameters."); + token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN); + if (token == null) { + logger.debug("Token not found in request parameters. Not an OAuth2 request."); + } else { + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE); + } + } + + return token; + } + + /** + * Extract the OAuth bearer token from a header. + * + * @param request The request. + * @return The token, or null if no OAuth authorization header was supplied. + */ + protected String extractHeaderToken(HttpServletRequest request) { + Enumeration headers = request.getHeaders("Authorization"); + while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that) + String value = headers.nextElement(); + if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) { + String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim(); + // Add this here for the auth details later. Would be better to change the signature of this method. + request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, + value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim()); + int commaIndex = authHeaderValue.indexOf(','); + if (commaIndex > 0) { + authHeaderValue = authHeaderValue.substring(0, commaIndex); + } + return authHeaderValue; + } + } + + return null; + } + +} diff --git a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigResourceServerConfigurerAdapter.java b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigResourceServerConfigurerAdapter.java index a6d400f7..9adea93d 100644 --- a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigResourceServerConfigurerAdapter.java +++ b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/component/PigResourceServerConfigurerAdapter.java @@ -51,6 +51,8 @@ public class PigResourceServerConfigurerAdapter extends ResourceServerConfigurer private PermitAllUrlProperties permitAllUrl; @Autowired private RestTemplate lbRestTemplate; + @Autowired + private PigBearerTokenExtractor pigBearerTokenExtractor; /** * 默认的配置,对外暴露 @@ -80,6 +82,7 @@ public class PigResourceServerConfigurerAdapter extends ResourceServerConfigurer remoteTokenServices.setRestTemplate(lbRestTemplate); remoteTokenServices.setAccessTokenConverter(accessTokenConverter); resources.authenticationEntryPoint(resourceAuthExceptionEntryPoint) + .tokenExtractor(pigBearerTokenExtractor) .accessDeniedHandler(pigAccessDeniedHandler) .tokenServices(remoteTokenServices); }