首页 > 解决方案 > 它没有 HTTP ok 状态-haproxy 后面的 Spring boot keycloak 版本 4.0.0 final

问题描述

我在使用 keycloak 进行身份验证的 spring boot 应用程序时遇到问题,我有这个应用程序位于 haproxy 后面,并试图完全禁用 spring 应用程序上的 cors 并在代理端管理它,但是我仍然遇到 cors 问题。“它没有 HTTP ok 状态”

注意我使用的是旧版本的 spring boot keycloak 插件,因为原始应用程序使用的是 spring boot 版本 1.5.10 请在附件中找到我探索过的一些配置选项:

案例 1:在 spring 应用程序上禁用 cors ----------------------------------------- --------

此设置返回响应预检标头上不存在的 http 状态正常

 @Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;

public SecurityWithoutCsrfConfig() {
    super();
}

// Submits the KeycloakAuthenticationProvider to the AuthenticationManager
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
}

@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
}

// Specifies the session authentication strategy
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Override
public void configure(final WebSecurity web) throws Exception {

    web.ignoring().antMatchers("/resources/**",
            "/v2/api-docs",
            "/swagger-ui.html",
            "/swagger2-ui.html",
            "/springfox/**",
            "/v2/swagger.json",
            "/_twilio/**",
            "/webjars/**",
            "/configuration/**",
            "/swagger-resources/**");
}

@Override
protected void configure(final HttpSecurity http) throws Exception {

    super.configure(http);

            http.csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers("/mypath/**").hasAnyRole("USER")
            .antMatchers("/mypath_admin/**").hasAnyRole("USER_ADMIN", "ADMIN")      
                    .anyRequest().fullyAuthenticated()
                    .and().httpBasic().and().cors().disable();
    http.headers().cacheControl();
}

案例 2:在 spring 应用程序端设置标题 --------------------------------------- --------

安全配置

@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;

public SecurityWithoutCsrfConfig() {
    super();
}

// Submits the KeycloakAuthenticationProvider to the AuthenticationManager
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
}

@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
}

// Specifies the session authentication strategy
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Override
public void configure(final WebSecurity web) throws Exception {

    web.ignoring().antMatchers("/resources/**",
            "/v2/api-docs",
            "/swagger-ui.html",
            "/swagger2-ui.html",
            "/springfox/**",
            "/v2/swagger.json",
            "/_twilio/**",
            "/webjars/**",
            "/configuration/**",
            "/swagger-resources/**");
}

@Override
protected void configure(final HttpSecurity http) throws Exception {

    super.configure(http);

    http.csrf().disable()
     .authorizeRequests()
     .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
     .antMatchers("/mypath/**").hasAnyRole("USER")
     .antMatchers("/mypath_admin/**").hasAnyRole("USER_ADMIN", "ADMIN")  
     .anyRequest().fullyAuthenticated()
     .and().httpBasic();

    http.headers().cacheControl();
}

网络配置

public class WebConfig extends WebMvcConfigurerAdapter {

/**
 * Adds Cross Origin Resource Sharing filter
 * @return CorsFilter
 */
@Bean
public CorsFilter corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");

    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
}

对于案例 2,我遇到了允许的原始标头问题。我的 haproxy 配置是您可以在任何官方 haproxy 网站上找到的标准设置。非常感谢上述任何解决方案或建议......最好是预检响应中http状态的解决方案。

标签: springspring-bootspring-securitykeycloakhaproxy

解决方案


为了进一步调试这种情况,我在我的 securityconfig 类的 configure 方法中添加了一个记录器,因为这是我怀疑请求中断的地方

        LOG.info("  --executing: configure(HttpSecurity)");

事实上我在这个类中有一个记录器,这意味着更多的配置细节将被打印到应用程序的输出中,所以我构建了 jar,将它复制到服务器并运行我的 jar 文件。当我重新加载最初给我 cors 错误的请求(飞行前不存在 http 正常状态)时,日志打印出 SSL 握手异常,这告诉我在我的应用程序配置中的某处它被设置为只期望通过 https 进行连接或安全端口。但是情况并非如此,我使用的是暴露在安全端口上的 haproxy,将连接转发到 jar 正在侦听的端口(8080)。因此,我仔细检查了整个应用程序的所有安全配置,在我的应用程序属性中,我发现我的设置错误

keycloak.ssl-required=all

所以我删除了这个设置,部署了应用程序,瞧,问题被避免了。希望这对任何有类似问题的人有所帮助。


推荐阅读