Spring Security OAuth2 授权码模式自定义 Redirect URL 重定向路径和 AuthorizationRequestBaseUri 跳转登录页的处理 URL
Spring Security OAuth2 Spring Boot About 6,894 words说明
本文以spring-boot-starter-oauth2-client 3.1.5
、Keycloak
为例。
默认跳转到登录页路径
OAuth2AuthorizationRequestRedirectFilter
过滤器中的DEFAULT_AUTHORIZATION_REQUEST_BASE_URI
常量
public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilter {
public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
}
默认登录成功跳转路径
OAuth2LoginAuthenticationFilter
过滤器中的DEFAULT_FILTER_PROCESSES_URI
常量。
public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*";
}
自定义路径
配置文件
配置文件中指定redirect-uri
,默认的认证成功后重定向的地址是{baseUrl}/{action}/oauth2/code/{registrationId}
。
spring:
security:
oauth2:
client:
registration:
keycloak:
provider: keycloak
client-id: my-client
client-secret:
redirect-uri: "{baseUrl}/api/oauth2/code/{registrationId}"
scope:
- openid
配置规则
DefaultOAuth2AuthorizationRequestResolver
中配置的baseUri
是Spring Security OAuth2 Client
处理跳转到Keycloak
登录页面时生成参数的URL
链接。
@Slf4j
@Configuration
@EnableWebSecurity
public class WebConfig {
@Bean
@Order(0)
SecurityFilterChain securityFilterChain0(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) throws Exception {
http
.securityMatcher( "/api/**", "/api/oauth2/**")
.formLogin(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.anonymous(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizeHttpRequests -> {
authorizeHttpRequests.anyRequest().authenticated();
})
.oauth2Login(login -> {
login.authorizationEndpoint(authorizationEndpoint -> {
DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, "/api/oauth2/authorization");
resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce());
authorizationEndpoint.authorizationRequestResolver(resolver);
authorizationEndpoint.baseUri("/api/oauth2/authorization");
});
login.loginProcessingUrl("/api/oauth2/code/keycloak");
})
;
return http.build();
}
}
源码
从源码中可以到{action}
会被替换为默认的login
,这样就是DEFAULT_FILTER_PROCESSES_URI
中的/login/oauth2/code/*
路径了。
private static ClientRegistration.Builder withProviderConfiguration(AuthorizationServerMetadata metadata, String issuer) {
String metadataIssuer = metadata.getIssuer().getValue();
String name = URI.create(issuer).getHost();
ClientAuthenticationMethod method = getClientAuthenticationMethod(metadata.getTokenEndpointAuthMethods());
Map<String, Object> configurationMetadata = new LinkedHashMap<>(metadata.toJSONObject());
// @formatter:off
return ClientRegistration.withRegistrationId(name)
.userNameAttributeName(IdTokenClaimNames.SUB)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.clientAuthenticationMethod(method)
.redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") // 默认配置
.authorizationUri((metadata.getAuthorizationEndpointURI() != null) ? metadata.getAuthorizationEndpointURI().toASCIIString() : null)
.providerConfigurationMetadata(configurationMetadata)
.tokenUri(metadata.getTokenEndpointURI().toASCIIString())
.issuerUri(issuer)
.clientName(issuer);
// @formatter:on
}
public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
String registrationId = resolveRegistrationId(request);
String redirectUriAction = getAction(request, "login");
return resolve(request, registrationId, redirectUriAction);
}
private String getAction(HttpServletRequest request, String defaultAction) {
String action = request.getParameter("action");
if (action == null) {
return defaultAction;
}
return action;
}
private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) {
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
OAuth2AuthorizationRequest.Builder builder = getBuilder(clientRegistration);
String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction);
// @formatter:off
builder.clientId(clientRegistration.getClientId())
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
.redirectUri(redirectUriStr)
.scopes(clientRegistration.getScopes())
.state(DEFAULT_STATE_GENERATOR.generateKey());
// @formatter:on
this.authorizationRequestCustomizer.accept(builder);
return builder.build();
}
private static String expandRedirectUri(HttpServletRequest request, ClientRegistration clientRegistration, String action) {
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("registrationId", clientRegistration.getRegistrationId());
// @formatter:off
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
.replacePath(request.getContextPath())
.replaceQuery(null)
.fragment(null)
.build();
// @formatter:on
String scheme = uriComponents.getScheme();
uriVariables.put("baseScheme", (scheme != null) ? scheme : "");
String host = uriComponents.getHost();
uriVariables.put("baseHost", (host != null) ? host : "");
// following logic is based on HierarchicalUriComponents#toUriString()
int port = uriComponents.getPort();
uriVariables.put("basePort", (port == -1) ? "" : ":" + port);
String path = uriComponents.getPath();
if (StringUtils.hasLength(path)) {
if (path.charAt(0) != PATH_DELIMITER) {
path = PATH_DELIMITER + path;
}
}
uriVariables.put("basePath", (path != null) ? path : "");
uriVariables.put("baseUrl", uriComponents.toUriString());
uriVariables.put("action", (action != null) ? action : "");
return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUri())
.buildAndExpand(uriVariables)
.toUriString();
}
}
Views: 1,180 · Posted: 2024-05-15
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...