首页 > 解决方案 > Spring Boot Security + Keycloak 适配器 401 响应当令牌过期而 antMatchers 是 permitAll()

问题描述

当我登录时,我会收到 access_token 和 refresh_token,我会将它们作为标头发送到 Spring 引导服务器的每个 HTTP 请求中。

我遇到的问题是,当令牌过期时,当我尝试访问无需身份验证即可访问的路由时,我得到 401 响应,因此结果是我无法访问 /v1/users/current,它检查令牌是否有效,如果不使用刷新令牌和给我一个新的访问令牌。

我现在要做的是使 /v1/users/current 无需任何类型的授权/身份验证即可访问,因此我可以接收新的访问令牌,但我不确定如何使用 KeycloakWebSecurityConfigurerAdapter 来实现。

我尝试使用 HandlerInterceptor,但我收到的 preHandle 请求已经通过 keycloak,我收到类似 401 的错误。

提前致谢!

编辑:当我使用 POSTMAN 并向 /v1/users/current 发送没有访问令牌(无身份验证)且在标头中有刷新令牌的获取请求时,我仍然可以访问 /v1/users/current 路由并获取新的访问令牌我需要。

    @KeycloakConfiguration
class ResourceServerConfiguration extends KeycloakWebSecurityConfigurerAdapter {


    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
        //the below three lines will add the relevant CORS response headers
        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


    @Bean
    public ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
        return new ServletListenerRegistrationBean<>(new HttpSessionEventPublisher());
    }


    @Autowired
    public void configureGlobal(
            AuthenticationManagerBuilder auth) throws Exception {

        KeycloakAuthenticationProvider keycloakAuthenticationProvider
                = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
                new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

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



    @Override
    public void configure(HttpSecurity http) throws Exception {


        http
                .csrf().disable()
                .cors().configurationSource(corsConfigurationSource())
                .and()
                .authorizeRequests().antMatchers(HttpMethod.GET,"/v1/users/current").permitAll().and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/login").permitAll()
                .antMatchers(HttpMethod.POST,"/register/admin").hasRole("admin")
                .antMatchers(HttpMethod.POST, "/*")
                .authenticated()
                .anyRequest()
                .permitAll();
    }

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

        web.ignoring().antMatchers(HttpMethod.GET,"/v1/users/current");
    }*/

}

标签: spring-bootkeycloak

解决方案


似乎 KeycloakAuthenticationProcessingFilter 正在检查每个具有 Authorization HTTP 标头的 http 请求,这意味着如果您需要访问路由而不检查它,您可以在没有 Authorization 标头的情况下发送它。

我已将我的 /v1/users/current 更改为没有标头的 POST,并且我正在请求正文中发送 access_token 和 refresh_token。


推荐阅读