使用 oauth2 授权代码和客户端凭据流配置 Spring 网络应用程序(非启动)问题

Issue configuring Spring web app(non-boot) with both oauth2 authorization code and client credential flow

目前 spring(非 spring 引导,无 application.properties)具有 web.xml 的 mvc 应用程序具有视图页面和休息端点资源。

应用程序的视图部分需要使用 idp 生成的登录页面通过 oidc openid 登录保护。

其余端点(特定其余 url 字符串映射)需要受客户端凭据授权保护,以便某些客户端应用程序访问。

视图和剩余资源都位于 /app/ servlet 映射*

我能够配置 spring 安全性以通过 oidc 登录保护视图页面,根据应用程序根目录的请求,我看到了 okta 登录页面,进入 username/pass, 我能够进入应用程序的主页。

我目前遇到的问题是如何为 spring 安全性设置客户端凭据流。

我无法在网上找到任何有关在一个应用程序中设置多个流程的资源,任何输入都适用。

谢谢。

以下是我仅针对 oidc 的工作配置。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring()
                .antMatchers("/css/**", "/js/**")
                .antMatchers("/public/healthcheck/status")
                .antMatchers("/app/rest/endpoint**");//this is one of the rest endpoint I was trying to protect via client credential flow, for now I have it bypass security or else it lives behind the oidc login
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests(authorize -> authorize
                        .antMatchers("/app/**").authenticated()
                )
                .oauth2Login(oauth2 -> oauth2
                        .redirectionEndpoint(redirection -> redirection
                                .baseUri("/login/oauth2/code/okta")
                        )
                );
    }

    @Bean
    public ClientRegistrationRepository clientRegistrationRepository() {
        return new InMemoryClientRegistrationRepository(this.oktaClientRegistration());
    }

    @Bean
    public OAuth2AuthorizedClientService authorizedClientService(
            ClientRegistrationRepository clientRegistrationRepository) {
        return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
    }

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository(
            OAuth2AuthorizedClientService authorizedClientService) {
        return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
    }

    private ClientRegistration oktaClientRegistration() {
        return ClientRegistrations
                .fromIssuerLocation("https://company-dev.oktapreview.com")
                .clientId("xxxx")
                .clientSecret("yyyyy-cccc")
                .scope("openid", "email", "profile")
                .registrationId("okta")
                .clientName("myappname")
                .redirectUriTemplate("{baseUrl}/login/oauth2/code/okta").build();
    }

您可以创建带有 @Order 注释的 multiple WebSecurityConfigurerAdapter instances。仅使用匹配的第一个 HttpSecurity

对于您的情况,您可能有如下所示的内容:

@EnableWebSecurity
public class MultiHttpSecurityConfig {
    // ...

    @Configuration
    @Order(1) // look at this configuration first                                                        
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http
                // this ENTIRE HttpSecurity only applies to URLs starting with /app/rest/
                .antMatcher("/app/rest/**")                            
                .authorizeRequests(authorize -> authorize
                    .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                    .jwt(jwt -> jwt
                        .jwkSetUri("https://idp.example.com/.well-known/jwks.json")
                     )
               );
        }
    }

    @Configuration
    // no @Order so use the default of last                                                   
    public static class OidcSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                // no matchers on HttpSecurity so use default of all requests
                // note that each HttpSecurity is attempted and only the first is used
                // this means requests starting with /app/rest/ will not use this configuration
                .authorizeRequests(authorize -> authorize
                    .anyRequest().authenticated()
                )                    
                .oauth2Login(oauth2 -> oauth2
                    .redirectionEndpoint(redirection -> redirection
                            .baseUri("/login/oauth2/code/okta")
                    )
                );
        }
    }
}