Keycloak 表示 403 禁止使用 GET 以外的 HTTP 方法

Keycloak says 403 Forbidden for HTTP Methods other than GET

我正在设置一个 Keycloak 实例以与包含 spring 安全性的 spring 启动应用程序一起使用。我使用邮递员来测试服务。我从获取新的访问令牌开始,效果很好。当我对安全端点执行 HTTP GET 调用时 - 一切正常,返回工作人员。但是当我对安全端点进行 HTTP POST/PUT/DELETE 调用时,Keycloak 显示错误 403 禁止访问。请看一看,告诉我哪里出了问题。

我已经测试了 http.csrf().disable() 选项,然后工作正常,但它不是生产的解决方案。

SecurityConfig.java

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {


    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

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

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers( "/api/**").hasRole("my_admin")
                .anyRequest().permitAll();
    }

application.yml:

keycloak:
  auth-server-url: http://localhost:11080/auth
  realm: myrealm
  resource: myclient
  public-client: true
  principal-attribute: preferred_username
  ssl-required: external
  use-resource-role-mappings: true

来自应用程序的一些日志(keycloak 跟踪日志级别):

2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:1080/api/my-endpoint
2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /api/my-endpoint
2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler        : AuthenticatedActionsValve.invoke http://localhost:1080/api/my-endpoint
2019-04-01 14:04:54.741 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler        : Policy enforcement is disabled.
2019-04-01 14:04:54.742 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:1080/error
2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator        : --> authenticate()
2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator        : try bearer
2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator    : Found [1] values in authorization header, selecting the first value for Bearer.
2019-04-01 14:04:54.743 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator    : Verifying access_token
2019-04-01 14:04:54.743 TRACE 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator    :     access_token: eyJhbs...blablab....signature
2019-04-01 14:04:54.744 DEBUG 2952 --- [io-1080-exec-10] o.k.a.BearerTokenRequestAuthenticator    : successful authorized
2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] o.k.a.RefreshableKeycloakSecurityContext : checking whether to refresh.
2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils       : useResourceRoleMappings
2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils       : Setting roles: 
2019-04-01 14:04:54.744 TRACE 2952 --- [io-1080-exec-10] org.keycloak.adapters.AdapterUtils       :    role: my_admin
2019-04-01 14:04:54.744 DEBUG 2952 --- [io-1080-exec-10] a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [my_admin] 
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator        : User 'my_user' invoking 'http://localhost:1080/error' on client 'myclient'
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.adapters.RequestAuthenticator        : Bearer AUTHENTICATED
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@fb0506b7: Principal: my_user; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@ecf147d; Granted Authorities: ROLE_my_admin
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler        : AuthenticatedActionsValve.invoke http://localhost:1080/error
2019-04-01 14:04:54.745 DEBUG 2952 --- [io-1080-exec-10] o.k.a.AuthenticatedActionsHandler        : Policy enforcement is disabled.

它是由Spring Security 提供的CSRF 保护。您真的需要使用 Keycloak 令牌提供这种保护吗?令牌仅包含在 cookie 中,或者也存在于授权中 header?

我发现我没有在 ajax 请求中使用 CSRF 令牌。 Spring 安全自动启用 CSRF 保护。 CSRF 令牌是为首次调用 Web 服务自动生成的,它具有 session 范围。您需要将该令牌保存在元标记中。每个 non-GET 请求都需要包含 CSRF 令牌(GET 请求不需要使用 CSRF 令牌保护,因为它们旨在 non-modifying API 调用)。


解决方案:只需要在 html 页面 (thymeleaf) 的 header 中包含该行:
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> <meta id="_csrf" name="_csrf" th:content="${_csrf.token}"/>

并在 ajax 调用 header:
中使用它 headers: { 'X-CSRF-TOKEN': $('#_csrf').attr('content') },

你应该做以下两个配置:

  1. 在 spring 配置中禁用 csrf http.csrf().disable()
  2. client 中定义角色而不是 realm 并为用户分配客户端级别角色