我目前正在开发一个演示原型,通过Spring Gateway保护Spring服务免受Keycloak攻击。在我目前的配置下,每次我访问网关中的一个MapURL时,它都会将我重定向到keycloak的登录屏幕,在引入我的凭据后,它会将我重定向到服务,结果会显示在屏幕上。现在,我正在尝试使用角色来保护服务中的特定端点,因此任何试图访问它们的用户都需要具有特定的角色。为了做到这一点,我在配置中添加了“@EnableMethodSecurity”注解,如下所示:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated()).oauth2ResourceServer((oauth2ResourceServer) -> oauth2ResourceServer.jwt((jwt) -> jwt.decoder(jwtDecoder())));
//OLD http.authorizeRequests(authorize -> authorize.anyRequest().authenticated()).oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri("http://[KEYCLOAK_IP]:8080/realms/my-realm/protocol/openid-connect/certs").build();
}
}
字符串
我还向服务的一个端点添加了“@PreAuthorize(“hasRole('myrole')”)注解,如下所示:
@Controller
public class ExampleController {
@PreAuthorize("hasRole('myrole')")
@GetMapping("/securedexample")
@ResponseBody
public String getString(){
return "secured string";
}
@GetMapping("/getToken")
@ResponseBody
public String getString2(){
Jwt token =(Jwt)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return "Value of the token:*******" + token.getTokenValue() + "*******";
}
型
每次我尝试访问使用@PreAuthorize注解保护的服务时,无论我登录的用户是谁,我都会在浏览器中看到一个空白屏幕,并且可以在日志中看到以下内容:
第一个月
它似乎没有在登录的用户中找到该角色。我在keycloak上有2个用户,每个用户都有不同的角色(myrole和myrole 2),当我检查登录用户(具有正确角色的用户)的JWS令牌的内容时,我可以看到它具有该角色。接下来,我粘贴令牌的相关部分:
...
"realm_access": {
"roles": [
"offline_access",
"uma_authorization",
"myrole", <-- The role is here!
"default-roles-my-realm"
]
},
...
型
我在互联网上搜索了一下,发现了几种保护和端点的代码变体:
@PreAuthorize("hasRole('myrole')")
@PreAuthorize("hasRole('ROLE_myrole')")
@PreAuthorize("hasAuthority('myrole')")
@PreAuthorize("hasAuthority('ROLE_myrole')")
型
我已经尝试了所有4个变化,没有运气。我也搜索并找到了这个链接PreAuthorize not working on Controller,但它似乎使用了上面相同的代码。有什么线索告诉我我做错了什么吗?提前感谢!
3条答案
按热度按时间qlvxas9a1#
似乎您没有为权限Map配置任何内容,默认的
Converter<Jwt, ? extends AbstractAuthenticationToken>
是JwtAuthenticationConverter
,它将Spring权限从scope
声明Map到SCOPE_
前缀。在配置
SecurityFilterChain
bean时,您应该定义自己的Converter<Jwt, ? extends AbstractAuthenticationToken>
。就像这样:个字符
但是你可能应该看看my starter,让事情在没有Java conf(只有应用程序属性)的情况下工作,而my tutorials则提供更多的背景,更多的用例和更灵活的权限转换器(一个比可以使用多个声明作为源代码,就像Pier-Jean Malandrino在他的回答中提到的
resource_access.{client-id}.roles
)。有了这些依赖关系:
型
这些yaml属性:
型
作为安全配置:
型
o7jaxewo2#
您是否检查了[领域和客户端角色之间的区别][1]?也许你的spring配置让你看到了错误的角色类型。
[1]:https://stackoverflow.com/questions/47837613/how-are-keycloak-roles-managed#:~:text= Keycloak%20has%20two%20categories%20of,%2C%20represented%20by%20the%20realm)。
mlnl4t2r3#
ch 4 mp提供的代码(有一些小的修改)工作起来很有魅力!非常感谢你的帮助,你值得一个纪念碑!