【问题标题】:Support for multiple grant_type with Spring security in the same application在同一个应用程序中支持多个具有 Spring 安全性的 grant_type
【发布时间】:2022-03-28 22:43:55
【问题描述】:

是否可以在 Spring Security 中轻松配置应用程序以使用 2 个不同的 grant_type?

我们的 Java BE 应用程序将通过 Angular FE 应用程序供 2 种不同类型的用户使用。用户类型定义为请求头:

  • 员工:必须使用 authorization_code 进行身份验证。
  • Internet 上的普通用户:他们通过 client_credentials 进行身份验证。

我们设法在 application.properties 中定义了这个:

#employee user
spring.security.oauth2.client.registration.employee.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.employee.authorization-uri=https://saml.company.com/oauth/authorize
spring.security.oauth2.client.registration.employee.redirect-uri=https://appDomain.com/appContext/login/oauth2/code/employee
spring.security.oauth2.client.provider.employee.token-uri=https://saml.company.com/oauth/token
spring.security.oauth2.client.registration.employee.scope=theScope
spring.security.oauth2.client.registration.employee.client-id=CLIENT_ID1
spring.security.oauth2.client.registration.employee.client-secret=SECRET

#general user
spring.security.oauth2.client.registration.direct.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.direct.token-uri=https://saml.company.com/oauth/token
spring.security.oauth2.client.registration.direct.client-id=CLIENT_ID2
spring.security.oauth2.client.registration.direct.client-secret=SECRET

这样做的主要问题是,针对两种用户类型(员工和普通用户)的未经身份验证的调用被重定向到标准 Spring /login 页面,该页面显示 2 个指向 2 个不同流 /grant_type 的 HTML 锚链接。

要求的行为是:

  • 让员工用户直接重定向到 spring.security.oauth2.client.provider.employee.authorization-uri 以根据 authorization_code 流动。
  • 对于一般用户,BE 应该处理 client_credentials 流,因为没有用户交互。

我们已尝试使用过滤器来避免 /login 重定向无济于事。有什么想法吗?

【问题讨论】:

  • 您可以编写自定义登录页面而不是默认登录页面。
  • 你用的是什么spring security版本?据我了解,该配置的作用是,它在您的 BE 应用程序客户端存储库中创建两个 oauth2 客户端,因此您的 BE 应用程序可以有两个 oauth2 客户端与外部 oauth2 资源服务器进行通信。这就是你想要的吗?

标签: spring spring-boot spring-security oauth-2.0 spring-security-oauth2


【解决方案1】:

您可以为每个不同的 URI 定义多个 WebSecurityConfigurerAdapter,如下所示。

@EnableWebSecurity
public class SecurityConfig {


@Configuration
@Order(1)
public static class SubscriptionWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        LOGGER.debug("SubscriptionWebSecurityConfigurerAdapter.configure start");
        // Enable CORS and disable CSRF
        http = http.cors().and().csrf().disable();

        // Set session management to stateless
        http = http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and();


        // Set unauthorized requests exception handler
        http = http
                .exceptionHandling()
                .authenticationEntryPoint(
                        (request, response, ex) -> {
                            response.sendError(
                                    HttpServletResponse.SC_UNAUTHORIZED,
                                    ex.getMessage()
                            );
                        }
                )
                .and();

        http.authorizeRequests()
            .antMatchers("/subs**").permitAll()
                .and()  ;

        LOGGER.debug("SubscriptionWebSecurityConfigurerAdapter.configure end");
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers("/subs**");
    }
}

@Configuration
@Order(2)
public static class ManagementWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        LOGGER.debug("ManagementWebSecurityConfigurerAdapter.configure start");
        http.antMatcher("/management/**")
            .authorizeRequests()
            .mvcMatchers("/management/monitoringService/taskmanagers").hasAnyRole("ADMIN", "OPERATOR")
            .mvcMatchers("/management/sendOperationReport").hasAnyRole("ADMIN", "OPERATOR", "CONSUMER")
            .anyRequest().permitAll();

        LOGGER.debug("ManagementWebSecurityConfigurerAdapter.configure end");
    }

}

@Order(3)
@Configuration
public static class WPSWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    private final String issuer;

    public WPSWebSecurityConfigurerAdapter(OAuth2ResourceServerProperties resourceServerProps) {
        this.issuer = resourceServerProps.getJwt().getIssuerUri();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        LOGGER.debug("WPSWebSecurityConfigurerAdapter.configure start");
        http.antMatcher("/wps/**")
            .authorizeRequests()
            .mvcMatchers("/wps/WebProcessingService").authenticated()
            .anyRequest().authenticated()
            .and().oauth2ResourceServer()
            .authenticationEntryPoint(new CustomOAuth2AuthenticationEntryPoint())
            .accessDeniedHandler(new CustomOAuth2AccessDeniedHandler())
            .jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());

        LOGGER.debug("WPSWebSecurityConfigurerAdapter.configure end");
    }

    @Bean
    JwtDecoder jwtDecoder() {
        LOGGER.debug("WPSWebSecurityConfigurerAdapter.jwtDecoder start");
        NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromOidcIssuerLocation(issuer);
        OAuth2TokenValidator<Jwt> validatorWithIssuer = JwtValidators.createDefaultWithIssuer(issuer);
        DelegatingOAuth2TokenValidator validator = new DelegatingOAuth2TokenValidator<>(validatorWithIssuer);
        jwtDecoder.setJwtValidator(validator);
        LOGGER.debug("WPSWebSecurityConfigurerAdapter.jwtDecoder end");
        return jwtDecoder;
    }

    private JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix("");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }
}

}

【讨论】:

    猜你喜欢
    • 2016-05-25
    • 2021-06-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2014-08-12
    • 2014-02-08
    • 2018-06-24
    • 2011-03-29
    相关资源
    最近更新 更多