首页 > 解决方案 > Spring Security:不同路径的多个 OpenID Connect 客户端?

问题描述

使用 Spring Boot 2.1.5 和 Spring Security 5,我尝试使用两个不同的 OpenID 客户端(基于 Keycloak)。这是我们在application.properties.

spring.security.oauth2.client.registration.keycloak-endusersclient.client-id=endusersclient
spring.security.oauth2.client.registration.keycloak-endusersclient.client-secret=7b41aaa4-277f-47cf-9eab-91afacd55d2c
spring.security.oauth2.client.provider.keycloak-endusersclient.issuer-uri=https://mydomain/auth/realms/endusersrealm

spring.security.oauth2.client.registration.keycloak-employeesclient.client-id=employeesclient
spring.security.oauth2.client.registration.keycloak-employeesclient.client-secret=7b41aaa4-277f-47cf-9eab-91afacd55d2d
spring.security.oauth2.client.provider.keycloak-employeesclient.issuer-uri=https://mydomain/auth/realms/employeesrealm

您可以从上面的代码片段中看到,我们正在尝试将一个 OpenID 客户端用于最终用户(客户),另一个用于员工。

在安全配置类中,我们看到如何在不同的模式上配置安全性,如下所示:

public class OpenIDConnectSecurityConfig extends
WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception {

    // avoid multiple concurrent sessions
    http.sessionManagement().maximumSessions(1);


    http.authorizeRequests()
            .antMatchers("/endusers/**").authenticated()
            .antMatchers("/employees/**").authenticated()
            .anyRequest().permitAll().and()
            .oauth2Login()
            .successHandler(new OpenIDConnectAuthenticationSuccessHandler())
            .and()
            .logout().logoutSuccessUrl("/");

我不明白的是如何配置每个 OpenID 客户端以触发单独的 URL 模式。在上面的示例中,我们希望看到在点击以“/endusers”开头的 URL 时使用 endusers 客户端,并在点击以“/employees”开头的 URL 时使用 employees 客户端。

这可以做到吗?

标签: springspring-bootspring-security

解决方案


对于多租户情况,您需要使用 AuthenticationManagerResolver,其中 endusersclient 和 employeesclient 是您的租户。

public class CustomAuthenticationManagerResolver implements AuthenticationManagerResolver<HttpServletRequest> {


@Override
public AuthenticationManager resolve(HttpServletRequest request) {
    return fromTenant();
}

private AuthenticationManager fromTenant(HttpServletRequest request) {
            String[] pathParts = request.getRequestURI().split("/");
//TODO find your tanent from the path and return the auth manager
}

// 在你的类中,它应该如下所示

private CustomAuthenticationManagerResolver customAuthenticationManagerResolver;

http.authorizeRequests()
        .antMatchers("/endusers/**").authenticated()
        .antMatchers("/employees/**").authenticated()
        .anyRequest().permitAll().and().oauth2ResourceServer().authenticationManagerResolver(this.customAuthenticationManagerResolver);

推荐阅读