我在试着做一件简单的事情。
要向单个终结点发出请求并(从客户端)发送承载令牌,我希望验证该令牌,并根据在我的终结点上的密钥遮盖接受/拒绝请求中分配的角色。
我看了很多教程,甚至是书,但大多数我就是看不懂。
按照此步骤设置我的密钥遮盖信息(领域、角色、用户)https://medium.com/@bcarunmail/securing-rest-api-using-keycloak-and-spring-oauth2-6ddf3a1efcc2
所以,
我基本上使用一个客户端设置了我的密匙斗篷,该客户端是一个具有特定角色“User”的用户,并如下配置:
@Configuration
@KeycloakConfiguration
//@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConf extends KeycloakWebSecurityConfigurerAdapter
{
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http
.authorizeRequests()
.antMatchers("/user/*").hasRole("admin")
.antMatchers("/admin*").hasRole("user")
}
}
我不明白为什么在许多教程中我会看到这一点(作为最后一条规则):
.anyRequest().permitAll();
基本上,当我设置我没有安全性时,我可以在没有持有者令牌的情况下调用端点。
但当我把这作为最后一条规则时
.anyRequest().denyAll();
我总是得403分。
调试中,我发现了这个:
请求是处理身份验证
f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
o.k.a.BearerTokenRequestAuthenticator : Found [1] values in authorization header, selecting the first value for Bearer.
o.k.a.BearerTokenRequestAuthenticator : Verifying access_token
o.k.a.BearerTokenRequestAuthenticator : successful authorized
a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: []
o.k.adapters.RequestAuthenticator : User 'testuser' invoking 'http://localhost:9090/api/user/123' on client 'users'
o.k.adapters.RequestAuthenticator : Bearer AUTHENTICATED
f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
o.s.s.authentication.ProviderManager : Authentication attempt using org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider
o.s.s.core.session.SessionRegistryImpl : Registering session 5B871A0E2AF55B70DC8E3B7436D79333, for principal testuser
f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@355f68d6: Principal: testuser; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@5d7a32a9; Not granted any authorities
[nio-9090-exec-3] o.s.security.web.FilterChainProxy : /api/user/123 at position 8 of 15 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
nio-9090-exec-3] o.s.s.w.s.DefaultSavedRequest : pathInfo: both null (property equals)
[nio-9090-exec-3] o.s.s.w.s.DefaultSavedRequest : queryString: both null (property equals)
看起来我没有得到无名小卒的角色。
我的依赖项:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>6.0.1</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>6.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
我的问题?
我请求访问令牌,发送:
client_id -> my client from keycloak
username -> my user from keycloak
password -> my password from keycloak
grant_type -> password
client_secret -> from keycloak
我得到一个令牌,然后我用来请求我的应用程序endint。我的请求始终有效,无论我使用的是哪个端点(角色为USER或角色为ADMIN的)。
在我的房子里,我有这样的东西:
keycloak:
auth-server-url: http://localhost:8080/auth/
resource: users-api
credentials:
secret : my-secret
use-resource-role-mappings : true
realm: my-realm
realmKey: my-key
public-client: true
principal-attribute: preferred_username
bearer-only: true
你知道如何实际启用这种情况下的角色吗?
我必须配置客户端才能使用JWT吗?有什么好主意吗?
我还在我的端点上添加了注解
@Secured("admin")
@PreAuthorize("hasAnyAuthority('admin')")
但他们似乎什么都不做。
--编辑--
在修复URL以匹配资源之后,我仍然得到403。
"realm_access": {
"roles": [
"offline_access",
"admin",
"uma_authorization"
]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
这是不是与我的问题有关?
6条答案
按热度按时间xxb16uws1#
在调试堆栈中:我看到您正在调用
/api/user/123
,并且在您的安全配置中,您正在保护不同的/user/*
,请将您的安全性更改为:P.S:不需要注册
KeycloakAuthenticationProcessingFilter
和KeycloakPreAuthActionsFilter
tzxcd3kk2#
如果您查看日志,您会发现Keyshaak成功地验证了访问令牌,但没有任何授予权限。这就是为什么Spring不授权该请求,而您会得到HTTP403禁止:
这是因为Keyloak适配器配置为使用资源(即客户端级)角色Map,而不是领域级角色Map:
Use-resource-Role-mappings:如果设置为True,适配器将在令牌内部查找用户的应用程序级角色Map。如果为False,它将在领域级别查找用户角色Map。这是可选的。默认值为FALSE。
Here是关于适配器配置的链接。
因此,如果您希望通过领域角色获得授权,则属性应如下所示:
**注意:**如果您想同时使用领域级和客户端级角色Map,那么您应该重写KeyloakAuthenticationProvider.authate()方法,通过自己组合来提供所需的角色。
qxgroojn3#
permitAll:
每当您想要允许任何请求访问特定的资源/URL时,都可以使用permitAll。例如,每个人都应该可以访问登录URL。
DenyAll:
当您想要阻止特定URL的访问时,无论请求来自何处或由谁发出请求(管理员)
您还存在与URL和角色不匹配的问题(您向用户授予具有管理员权限的URL,反之亦然)。(最好使用ROLE_ADMIN或ADMIN或USER角色)从堆栈中我可以看到未授予任何权限,因此请与权威人士重新检查代码
sd2nnvve4#
1.你会在没有
@Configuration
的情况下尝试吗?我认为在SecurityConf
类上只需要@KeycloakConfiguration
注解。1.你的antMatcher是否尊重区分大小写?
1.也请尝试此配置,以删除Java定义的Role_*约定:
1.如果您的所有端点都有相同的逻辑,安全配置应该足够了,您不需要其他注解。但是,如果您有另一个具有admin角色的端点,而该端点不在您的“/api/admin”控制器中,您可以尝试:
omjgkv6w5#
回答晚了,但希望能对其他面临同样问题的人有所帮助。我面临着与您完全相同的问题,对于我来说,在Configuration类中,我必须通过设置授予的权限Map器(@Override方法仅用于调试)来更改默认的keyloakAuthenticationProvider:
}
4dc9hkyq6#
2022更新
用于Spring的密钥斗篷适配器是deprecated。不要用它。请改用
spring-boot-starter-oauth2-resource-server
。轻松解决
在
spring-boot-starter-oauth2-resource-server
之上有一个非常方便的set of libs,配置可以非常简单:纯 Spring 解决方案
要仅对
spring-boot-starter-oauth2-resource-server
执行相同的操作,需要编写相当多的Java conf:重要说明
上面的两种配置都没有转换到key shaak角色(大小写不变,没有
ROLE_
前缀),这是使用hasAuthority(...)
而不是hasRole(...)
的原因。此外,仅考虑在以下级别使用定义的角色: