如何将 Spring Boot 应用程序与 SAML 和 JWT 令牌集成:多个 WebSecurityConfigurerAdapter

Swa*_*hi 6 java saml jwt spring-boot okta

我尝试在 Spring Boot 应用程序中使用 JWT 令牌和 SAML。我的应用程序使用从 OKTA 返回的用户名创建 JWT 令牌。

流动:

  1. 单击 https://localhost:8088/my_app/ API 应用程序应重定向到 OKTA 登录页面,然后获取用户名作为响应。
  2. 根据用户名生成 JWT 令牌。
  3. 使用 JWT 令牌进行剩余的 APIS 身份验证。

我能够将应用程序导航到 OKTA 登录页面,对用户进行身份验证并获取用户名。然后,在此步骤之后,我尝试使用此用户名创建 JWT 令牌。

我面临的问题是,因为我有两个 WebSecurityConfigurerAdapter,一个用于 SAML 重定向,另一个用于 JWT,我无法限制 APIS 拥有 JWT 令牌。我的应用程序没有检查所有 API 中的 JWT 令牌。

当我禁用 SAML 时,JWT 可以正常工作,如果我禁用 JWT SAML 也可以正常工作。现在有人可以告诉我如何配置我的应用程序以使用 SAML 和 JWT Web 安全配置吗?

@Confguration
@EnableWebSecurity
public class SecurityConfig {
    @Order(1)
    @Configuration
    public static class SAMLConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;
        @Value("${security.saml2.metadata-url}")
        String metadataUrl;
        @Value("${server.ssl.key-alias}")
        String keyAlias;
        @Value("${server.ssl.key-store-password}")
        String password;
        @Value("${server.port}")
        String port;
        @Value("${server.ssl.key-store}")
        String keyStoreFilePath;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requestMatchers()
                    .antMatchers("/saml*").and()
                    .apply(saml())
                    .serviceProvider()
                    .keyStore()
                    .storeFilePath(this.keyStoreFilePath)
                    .password(this.password)
                    .keyname(this.keyAlias)
                    .keyPassword(this.password)
                    .and()
                    .protocol("https")
                    .hostname(String.format("%s:%s", "localhost", this.port))
                    .basePath("/my_app")
                    .and()
                    .identityProvider()
                    .metadataFilePath(this.metadataUrl);
        }

    }


    @Order(2)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
        @Autowired
        private UserDetailsService jwtUserDetailsService;
        @Autowired
        private JwtRequestFilter jwtRequestFilter;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            //encrypts user passweod so its not visible to outside world
            auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
        }

        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }


        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {


            httpSecurity.requestMatchers()
                    .antMatchers("/user/hello").and().authorizeRequests().anyRequest().authenticated().and().
                            exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            httpSecurity.cors();
            httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        }

        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
            return source;
        }


    }
}
Run Code Online (Sandbox Code Playgroud)