使用资源服务器中的用户角色限制路径上的访问 [英] Using user roles in resource server to restrict acces on path
问题描述
我希望使用新的Spring安全授权服务器为我的Web服务实现OAuth2。
在https://www.baeldung.com/spring-security-oauth-auth-server给出了一个例子,分离
- 授权服务器
- 资源服务器
- 客户端
代码位于https://github.com/Baeldung/spring-security-oauth/tree/master/oauth-authorization-server
这三个Maven项目在给定版本中运行,当Web浏览器中的客户端访问http://localhost:8080/articles时,输出是正确的
["Article 1","Article 2","Article 3"]
我需要根据用户上定义的角色限制对路径的访问,或者使用权限也可以。
在本例中,它在资源服务器中实现
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.mvcMatcher("/articles/**")
.authorizeRequests()
.mvcMatchers("/articles/**").access("hasAuthority('SCOPE_articles.read')")
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
我将其更改为
http
.authorizeRequests()
.antMatchers("/articles").hasRole("ADMIN")
还在授权服务器项目中使用.roles("ADMIN")
admin / admin123
用户
然而,当客户端访问我在客户端项目控制台中获得的http://localhost:8080/articles输出时,这并不能按预期运行
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET http://localhost:8090/articles] with root cause
org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET http://localhost:8090/articles
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:183) ~[spring-webflux-5.3.4.jar:5.3.4]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 403 from GET http://localhost:8090/articles [DefaultWebClient]
我找到了一个示例项目https://blog.jdriven.com/2019/10/spring-security-5-2-oauth-2-exploration-part1/,但不幸的是,它使用Keyshaak作为授权服务器,但实现了相同的想法,即限制访问具有用户角色的路径。
它定义了一个KeycloakRealmRoleConverter
,但是如何为给定的三个Baeldung项目定义一个?
使用Keyshaak的示例使用jwt.getClaims().get("realm_access")
,这显然是访问密钥realm_access
,但这与Keyshaak相关。
要打印出我在资源服务器REST控制器中更改的JWT令牌
@GetMapping("/articles")
public String[] getArticles(final @AuthenticationPrincipal Jwt
System.out.println("
jwt.getTokenValue():
" + jwt.getTokenValue());
...
}
在jwt.io
显示
HEADER:ALGORITHM & TOKEN TYPE
{
"kid": "fce0c3e4-a9a6-4e6d-8fbd-c2b774b338f0",
"typ": "JWT",
"alg": "RS256"
}
PAYLOAD:DATA
{
"sub": "admin",
"aud": "articles-client",
"nbf": 1628351323,
"scope": [
"articles.read"
],
"iss": "http://127.0.0.1:9000",
"exp": 1628351623,
"iat": 1628351323,
"jti": "c4bc5f35-e93f-483f-8952-a694a04f8f32"
}
此处未定义任何角色。我本以为用户名admin
旁边还会有为该用户定义的角色ADMIN
。
不确定如何限制对具有用户角色的资源服务器中的路径的访问(如果该路径不在JWT中)。
推荐答案
我们先来看看Spring Security中权限、角色和作用域之间的关系。
角色只是以ROLE_
为前缀的权限。配置
.antMatchers("/articles/**").hasRole("ADMIN")
等同于.antMatchers("/articles/**").hasAuthority("ROLE_ADMIN")
。默认情况下,资源服务器通过在每个值前面加上SCOPE_
前缀,根据";作用域";声明填充授权。在您提供的示例中,";作用域";声明包含";articles.read";,这意味着唯一的权限是
SCOPE_articles.read
。使用默认设置时,资源服务器没有角色概念,因为它没有以
ROLE_
为前缀的权限(它们都以SCOPE_
为前缀)。
授权服务器中提供了授予&admin";用户的角色&admin";。
它不是令牌的一部分,因为令牌不代表用户,而是授权客户端访问用户数据的特定部分。
如果资源服务器需要用户信息,我建议查看OpenID Connect Protocol。
Here是一个类似的问题,解释了为什么不应将作用域用于此目的。
这篇关于使用资源服务器中的用户角色限制路径上的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!