From ed876c4fb6e712bf19c1cdf6c3c5dbf81b50b360 Mon Sep 17 00:00:00 2001 From: xgblack Date: Sat, 24 Feb 2024 22:59:46 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat(auth):=20=E4=BF=AE=E6=94=B9=20?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E6=8E=88=E6=9D=83=E6=8E=A5=E5=8F=A3=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0=E6=96=B9=E5=BC=8F=E4=B8=BAform-data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 官方认为参数传递是不安全的,所以spring-boot自3.2.1版本起,需要使用form-data方式传参,参考https://github.com/spring-projects/spring-authorization-server/issues/1451 --- .../endpoint/CoolTokenEndpoint.java | 4 ++-- ...sourceOwnerBaseAuthenticationConverter.java | 8 ++++---- .../MobileGrantAuthenticationConverter.java | 6 +++--- .../PasswordGrantAuthenticationConverter.java | 8 ++++---- .../component/CoolBearerTokenExtractor.java | 3 +-- ...Utils.java => CoolOAuth2EndpointUtils.java} | 18 +++++++++++++----- 6 files changed, 27 insertions(+), 20 deletions(-) rename cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/{OAuth2EndpointUtils.java => CoolOAuth2EndpointUtils.java} (81%) diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/endpoint/CoolTokenEndpoint.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/endpoint/CoolTokenEndpoint.java index 48422bc..c477ebf 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/endpoint/CoolTokenEndpoint.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/endpoint/CoolTokenEndpoint.java @@ -3,7 +3,7 @@ package com.xgblack.cool.framework.security.core.authentication.endpoint; import com.xgblack.cool.framework.common.constants.CacheConstants; import com.xgblack.cool.framework.security.annotation.Inner; import com.xgblack.cool.framework.security.core.authentication.support.handler.CoolAuthenticationFailureEventHandler; -import com.xgblack.cool.framework.security.core.utils.OAuth2EndpointUtils; +import com.xgblack.cool.framework.security.core.utils.CoolOAuth2EndpointUtils; import com.xgblack.cool.framework.security.core.utils.OAuth2ErrorCodesExpand; import com.xgblack.cool.framework.security.service.RemoteClientDetailsService; import jakarta.servlet.http.HttpServletRequest; @@ -128,7 +128,7 @@ public class CoolTokenEndpoint { } Map claims = authorization.getAccessToken().getClaims(); - OAuth2AccessTokenResponse sendAccessTokenResponse = OAuth2EndpointUtils.sendAccessTokenResponse(authorization, claims); + OAuth2AccessTokenResponse sendAccessTokenResponse = CoolOAuth2EndpointUtils.sendAccessTokenResponse(authorization, claims); this.accessTokenHttpResponseConverter.write(sendAccessTokenResponse, MediaType.APPLICATION_JSON, httpResponse); } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/base/OAuth2ResourceOwnerBaseAuthenticationConverter.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/base/OAuth2ResourceOwnerBaseAuthenticationConverter.java index 20d02b4..7dbf225 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/base/OAuth2ResourceOwnerBaseAuthenticationConverter.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/base/OAuth2ResourceOwnerBaseAuthenticationConverter.java @@ -1,6 +1,6 @@ package com.xgblack.cool.framework.security.core.authentication.support.base; -import com.xgblack.cool.framework.security.core.utils.OAuth2EndpointUtils; +import com.xgblack.cool.framework.security.core.utils.CoolOAuth2EndpointUtils; import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -56,11 +56,11 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationConverter parameters = OAuth2EndpointUtils.getParameters(request); + MultiValueMap parameters = CoolOAuth2EndpointUtils.getParameters(request); // scope (OPTIONAL) String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE); if (StringUtils.hasText(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) { - OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + CoolOAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE, CoolOAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } Set requestedScopes = null; @@ -74,7 +74,7 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationConverter parameters = OAuth2EndpointUtils.getParameters(request); + MultiValueMap parameters = CoolOAuth2EndpointUtils.getParameters(request); // PHONE (REQUIRED) String phone = parameters.getFirst(SecurityConstants.SMS_PARAMETER_NAME); if (!StringUtils.hasText(phone) || parameters.get(SecurityConstants.SMS_PARAMETER_NAME).size() != 1) { - OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, SecurityConstants.SMS_PARAMETER_NAME, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + CoolOAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, SecurityConstants.SMS_PARAMETER_NAME, CoolOAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/password/PasswordGrantAuthenticationConverter.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/password/PasswordGrantAuthenticationConverter.java index 600b385..dbcef8d 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/password/PasswordGrantAuthenticationConverter.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/authentication/support/password/PasswordGrantAuthenticationConverter.java @@ -1,7 +1,7 @@ package com.xgblack.cool.framework.security.core.authentication.support.password; import com.xgblack.cool.framework.security.core.authentication.support.base.OAuth2ResourceOwnerBaseAuthenticationConverter; -import com.xgblack.cool.framework.security.core.utils.OAuth2EndpointUtils; +import com.xgblack.cool.framework.security.core.utils.CoolOAuth2EndpointUtils; import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.AuthorizationGrantType; @@ -43,17 +43,17 @@ public class PasswordGrantAuthenticationConverter extends OAuth2ResourceOwnerBas */ @Override public void checkParams(HttpServletRequest request) { - MultiValueMap parameters = OAuth2EndpointUtils.getParameters(request); + MultiValueMap parameters = CoolOAuth2EndpointUtils.getParameters(request); // username (REQUIRED) String username = parameters.getFirst(OAuth2ParameterNames.USERNAME); if (!StringUtils.hasText(username) || parameters.get(OAuth2ParameterNames.USERNAME).size() != 1) { - OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.USERNAME, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + CoolOAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.USERNAME, CoolOAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } // password (REQUIRED) String password = parameters.getFirst(OAuth2ParameterNames.PASSWORD); if (!StringUtils.hasText(password) || parameters.get(OAuth2ParameterNames.PASSWORD).size() != 1) { - OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.PASSWORD, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + CoolOAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.PASSWORD, CoolOAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } } diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java index a1d47a1..02e4814 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/component/CoolBearerTokenExtractor.java @@ -21,8 +21,7 @@ import java.util.regex.Pattern; public class CoolBearerTokenExtractor implements BearerTokenResolver { - private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", - Pattern.CASE_INSENSITIVE); + private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", Pattern.CASE_INSENSITIVE); private boolean allowFormEncodedBodyParameter = false; diff --git a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/OAuth2EndpointUtils.java b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/CoolOAuth2EndpointUtils.java similarity index 81% rename from cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/OAuth2EndpointUtils.java rename to cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/CoolOAuth2EndpointUtils.java index ce0a7c7..2cc195c 100644 --- a/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/OAuth2EndpointUtils.java +++ b/cool-framework/cool-spring-boot-starter-security/src/main/java/com/xgblack/cool/framework/security/core/utils/CoolOAuth2EndpointUtils.java @@ -1,8 +1,8 @@ package com.xgblack.cool.framework.security.core.utils; -import org.dromara.hutool.core.map.MapUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.experimental.UtilityClass; +import org.dromara.hutool.core.map.MapUtil; import org.springframework.security.oauth2.core.*; import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; @@ -10,6 +10,7 @@ import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import java.io.IOException; import java.time.temporal.ChronoUnit; @@ -21,21 +22,28 @@ import java.util.Map; */ @UtilityClass -public class OAuth2EndpointUtils { +public class CoolOAuth2EndpointUtils { public final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; /** * 解析Http请求参数 + *

认证方式同spring官方方式修改,认证方式改为form-data,不再支持query parameter, + * 自spring-boot3.2.1版本起修改,参见{@link org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2EndpointUtils#getFormParameters(HttpServletRequest)}

+ * * @param request * @return */ public MultiValueMap getParameters(HttpServletRequest request) { Map parameterMap = request.getParameterMap(); - MultiValueMap parameters = new LinkedMultiValueMap<>(parameterMap.size()); + MultiValueMap parameters = new LinkedMultiValueMap<>(); parameterMap.forEach((key, values) -> { - for (String value : values) { - parameters.add(key, value); + String queryString = StringUtils.hasText(request.getQueryString()) ? request.getQueryString() : ""; + // If not query parameter then it's a form parameter + if (!queryString.contains(key) && values.length > 0) { + for (String value : values) { + parameters.add(key, value); + } } }); return parameters; -- Gitee