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')
},
你应该做以下两个配置:
- 在 spring 配置中禁用 csrf
http.csrf().disable()
- 在 client 中定义角色而不是 realm 并为用户分配客户端级别角色
我正在设置一个 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')
},
你应该做以下两个配置:
- 在 spring 配置中禁用 csrf
http.csrf().disable()
- 在 client 中定义角色而不是 realm 并为用户分配客户端级别角色