Spring Security Spring中使用角色的安全方法

tyu7yeag  于 2023-08-05  发布在  Spring
关注(0)|答案(3)|浏览(114)

我目前正在开发一个演示原型,通过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,但它似乎使用了上面相同的代码。有什么线索告诉我我做错了什么吗?提前感谢!

qlvxas9a

qlvxas9a1#

似乎您没有为权限Map配置任何内容,默认的Converter<Jwt, ? extends AbstractAuthenticationToken>JwtAuthenticationConverter,它将Spring权限从scope声明Map到SCOPE_前缀。
在配置SecurityFilterChain bean时,您应该定义自己的Converter<Jwt, ? extends AbstractAuthenticationToken>。就像这样:

spring:
  security:
    oauth2:
      resourceserver:
        Jwk-set-uri: http://[KEYCLOAK_IP]:8080/realms/my-realm/protocol/openid-connect/certs

个字符
但是你可能应该看看my starter,让事情在没有Java conf(只有应用程序属性)的情况下工作,而my tutorials则提供更多的背景,更多的用例和更灵活的权限转换器(一个比可以使用多个声明作为源代码,就像Pier-Jean Malandrino在他的回答中提到的resource_access.{client-id}.roles)。
有了这些依赖关系:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <!-- For a reactive application, use spring-boot-starter-webflux instead -->
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

<dependency>
    <groupId>com.c4-soft.springaddons</groupId>
    <artifactId>spring-addons-starter-oidc</artifactId>
    <version>7.0.0</version>
</dependency>


这些yaml属性:

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
        - iss: {value of iss claim in one of your tokens} 
          jwk-set-uri: http://[KEYCLOAK_IP]:8080/realms/my-realm/protocol/openid-connect/certs
          username-claim: preferred_username
          authorities:
          - path: $.realm_access.roles
          - path: $.resource_access.*.roles
        resourceserver:
          permit-all:
          - "/greet/public"
          cors:
          - path: /**
            allowed-origin-patterns: http://localhost:4200


作为安全配置:

@Configuration
@EnableMethodSecurity
public class SecurityConfiguration {
}

o7jaxewo

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)。

mlnl4t2r

mlnl4t2r3#

ch 4 mp提供的代码(有一些小的修改)工作起来很有魅力!非常感谢你的帮助,你值得一个纪念碑!

相关问题