如何在Spring Authorization Server中重写Redirect URI验证为前缀匹配?
解决方案:重写Redirect URI为前缀匹配验证
由于Spring Authorization Server默认的OAuth2AuthorizationCodeRequestAuthenticationValidator遵循IETF规范实现精确匹配,但内部客户端存在可变查询参数导致验证失败,可通过以下步骤自定义验证逻辑实现前缀匹配:
1. 实现前缀匹配的Redirect URI验证器
自定义OAuth2RedirectUriValidator实现类,替换默认的精确匹配逻辑为前缀匹配:
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationContext; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; import org.springframework.security.oauth2.server.authorization.validation.OAuth2RedirectUriValidator; import org.springframework.util.StringUtils; public class PrefixMatchingRedirectUriValidator implements OAuth2RedirectUriValidator { @Override public void validate(OAuth2AuthorizationCodeRequestAuthenticationContext context) { String requestedRedirectUri = context.getAuthentication().getRedirectUri(); if (!StringUtils.hasText(requestedRedirectUri)) { return; } RegisteredClient registeredClient = context.getRegisteredClient(); // 检查请求的Redirect URI是否以注册的任意一个URI为前缀 boolean isMatch = registeredClient.getRedirectUris().stream() .anyMatch(registeredUri -> requestedRedirectUri.startsWith(registeredUri)); if (!isMatch) { throw new OAuth2AuthorizationCodeRequestAuthenticationException( OAuth2AuthorizationCodeRequestAuthenticationErrorCodes.INVALID_REQUEST, String.format("Invalid redirect URI: %s", requestedRedirectUri)); } } }
2. 自定义授权码请求验证器
封装默认验证逻辑与自定义Redirect URI验证器,确保其他规范验证逻辑正常执行:
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationContext; import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationValidator; import org.springframework.security.oauth2.server.authorization.validation.OAuth2RedirectUriValidator; public class CustomAuthorizationCodeRequestValidator implements OAuth2AuthorizationCodeRequestAuthenticationValidator { private final OAuth2RedirectUriValidator redirectUriValidator; public CustomAuthorizationCodeRequestValidator(OAuth2RedirectUriValidator redirectUriValidator) { this.redirectUriValidator = redirectUriValidator; } @Override public void validate(OAuth2AuthorizationCodeRequestAuthenticationContext context) { // 先执行官方默认的基础验证(客户端合法性、响应类型校验等) OAuth2AuthorizationCodeRequestAuthenticationValidator.DEFAULT.validate(context); // 执行自定义的前缀匹配验证 this.redirectUriValidator.validate(context); } }
3. 注册自定义验证器到Spring容器
在授权服务器配置类中替换默认的验证器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationValidator; @Configuration public class AuthorizationServerConfig { @Bean public OAuth2AuthorizationCodeRequestAuthenticationValidator authorizationCodeRequestAuthenticationValidator() { return new CustomAuthorizationCodeRequestValidator(new PrefixMatchingRedirectUriValidator()); } }
注意事项
- 确保注册客户端时配置的
redirect_uri是请求URI的固定前缀(例如注册http://internal-app/callback,则http://internal-app/callback?var=123可通过验证) - 此实现违反RFC 6749规范,仅限内部可信客户端使用,禁止对外暴露
- 若需忽略查询参数进行匹配,可修改
PrefixMatchingRedirectUriValidator,将请求URI截取到?之前再做前缀匹配
内容的提问来源于stack exchange,提问作者jmsjr
相关产品推荐
相关产品推荐

