【问题标题】:Spring Data Rest Secure HATEOAS linkSpring Data Rest Secure HATEOAS 链接
【发布时间】:2016-05-23 17:10:45
【问题描述】:

假设我有一个 User 实体,其 ManyToMany 映射到 UserGroup 实体。如果我为这两个实体创建存储库并获取 URI /users/1,我会收到如下响应:

{
  "enabled" : true,
  "password" : "xxxxxx",
  "username" : "xxxxxx",
  "credentialsNonExpired" : true,
  "accountNonLocked" : true,
  "accountNonExpired" : true,
  "_links" : {
    "self" : {
      "href" : "http://127.0.0.1:45950/users/1"
    },
    "user" : {
      "href" : "http://127.0.0.1:45950/users/1"
    },
    "userGroups" : {
      "href" : "http://127.0.0.1:45950/users/1/userGroups"
    }
  }
}

这里的 userGroups 链接真的很有用。

我可以使用/userGroups 端点列出所有UserGroups。 我想使用不同的spring-security 表达式来保护/userGroups 端点和/users/1/userGroups 端点。

在此处使用参考:http://docs.spring.io/spring-data/rest/docs/current/reference/html/#security 我了解如何保护第一个端点:

public interface UserGroupRepository extends PagingAndSortingRepository<UserGroup, Long> {

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Override
    Iterable<T> findAll();
}

但是如何保护第二个端点?目前这甚至可能吗?是否有针对此类功能的一些工作计划。我很乐意做出贡献。

【问题讨论】:

    标签: spring spring-security spring-data spring-data-rest


    【解决方案1】:

    我也遇到过这个问题,但没有找到任何使用 Spring 的安全注释的解决方案。作为一种解决方法,我添加了以下内容:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // Whatever config you already have.
            .authorizeRequests()
                .antMatchers("/users/*/userGroups").hasRole("ADMIN");
    }
    

    我对@9​​87654322@ 的实现。虽然这可行,但它重复了在保护存储库时所做的工作,并且在添加新存储库时很容易忘记同时添加 java 配置和注释。

    【讨论】:

      【解决方案2】:

      我意识到这个问题已经有四年了,但这个问题一直困扰着我,我终于找到了一些可行的方法。

      问题本质上归结为 Spring HATEOAS 没有真正的安全控制。虽然您可以使用适当的方法级安全注释配置存储库以防止通过 REST API 进行访问,但您无法阻止 HATEAOS 表示模型组装器吞食它可以看到的任何对象。

      我找到的解决方案是为EntityModel&lt;DomainObject&gt;s 公开一个RepresentationModelProcessor bean。在你的情况下,这可能看起来像

      @Configuration
      public class SecureHateoasConfig {
      
          public static class UserGroupProcessor implements RepresentationModelProcessor<EntityModel<UserGroup>> {
              @Override
              public EntityModel<UserGroup> process(EntityModel<UserGroup> model) {
                  if(SecurityContextHolder.getContext()
                      .getAuthentication()
                      .getAuthorities()
                      .stream()
                      .map(GrantedAuthority::getAuthority)
                      .anyMatch("ROLE_ADMIN"::equals)) {
                      return model;
                  } else {
                      return null;
                  }
              }
          }
      
          @Bean
          public UserGroupProcessor userGroupProcessor() {
              return new UserGroupProcessor();
          }
      
      }
      

      null 替换的对象似乎在正常处理后被过滤掉了,因此嵌入式实体根本不包括与您的过滤器不匹配的对象!

      如果你只做基于角色的安全,可能有一种更简单的方法来过滤链接,但恐怕我不知道......

      当然,可以大大扩展它,因为您的安全对象处理器不仅需要应用于EntityModel&lt;UserGroup&gt;!就我而言,我的所有安全域对象都实现了一个接口,可用于做出安全决策,因此只需要一个 RepresentationModelProcessor implementation/bean。

      【讨论】:

        猜你喜欢
        • 2013-10-31
        • 2014-03-07
        • 1970-01-01
        • 2014-11-17
        • 2014-08-16
        • 2014-07-05
        • 2018-07-23
        • 2018-11-26
        • 1970-01-01
        相关资源
        最近更新 更多