您如何保护 Spring Boot / Spring-Data Rest 以便用户只能访问他自己的实体

Posted

技术标签:

【中文标题】您如何保护 Spring Boot / Spring-Data Rest 以便用户只能访问他自己的实体【英文标题】:How do you secure SpringBoot / Spring-Data Rest so user can only access his own entities 【发布时间】:2016-02-15 15:11:10 【问题描述】:

我将 Spring-Data/Rest (http://docs.spring.io/spring-data/rest/docs/current/reference/html/) 与 Spring Boot 和基本 Spring Security 一起使用。

我有以下实体。

Items
  -->ID

User
 --> ID
 --> List<Items> items

目前使用弹簧架,任何用户都可以看到 /items/1,2,3,4,5

我只想让用户,只能看到他们自己的项目。

这是否可以在无需编写自定义控制器的情况下实现?

【问题讨论】:

【参考方案1】:

我认为 JPA 级别的多租户可能是一种很好的透明方法来分离用户可以看到的数据。请在此处查看我的答案以获取详细信息: https://***.com/a/33648305/5371736

【讨论】:

【参考方案2】:

是的,你可以。

为此,您可以为每个用户分配一个特定的角色。例如,在您的情况下,将拥有项目的用户分配为角色列 ADMIN 和所有其他匿名或用户,您可以选择。在此之后,使用 spring security对于项目 URL 具有 ANONYMOUS 或 USER 角色的用户,您可以使请求失败,并且只允许具有 ADMIN 角色的用户查看项目。

现在,这可以通过 Spring Security 以多种方式实现:

1.为单个控制器方法和测试角色ADMIN/USER/..使用@PreAuthorize标签 但是,我想,您不想如此大幅度地修改控制器。

    简单的手动方式,即在上下文持有者中创建身份验证对象并使用spring boot security config,例如:

     @Order(1)
     public class UserFilter extends Filter 
    
     @Autowired
     UserService userService;
     ...
    
     UserObject userObject = userService.getUser(arg..);
     List<GrantedAuthority> grantedAuthorityList = new ArrayList<GrantedAuthority>();
     grantedAuthorityList.add( new SimpleGrantedAuthority((userObject.getRoleName()));//Either ROLE_ADMIN or ROLE_USER
    Authentication authentication = new    PreAuthenticatedAuthenticationToken(userObject.getId(), new Object(), grantedAuthorityList);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    chain.doFilter(request,response);
    
    ...
    
    
    

以及安全配置类:

  @Configuration
  @EnableWebSecurity
  public class SecurityConfigREST extends WebSecurityConfigurerAdapter 


  SecurityConfigREST()
    super(true);
  
  @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
    PreAuthenticatedAuthenticationProvider pap=new PreAuthenticatedAuthenticationProvider();
    pap.setPreAuthenticatedUserDetailsService(new PreAuthenticatedGrantedAuthoritiesUserDetailsService());
    auth.authenticationProvider(pap);

@Override
  protected void configure(HttpSecurity http) throws Exception 
   http
      .authorizeRequests()
      .regexMatchers("^/items.*$").hasAuthority("ROLE_ADMIN") //The role which should have access to /items/1,2.. URL
      .anyRequest().authenticated();
  
   
    在上面的安全配置中使用 UserDetailsS​​ervice 并将用户及其角色加载到预先验证的身份验证提供程序中。 参考:http://docs.spring.io/autorepo/docs/spring-security/3.2.2.RELEASE/apidocs/org/springframework/security/core/userdetails/UserDetailsService.html

话虽如此,不通过 URL 传递项目 (1,2,3) 编号也是一个很好的设计,因为以后可能会导致潜在的问题,所以使用 GET 并将 JSON 请求正文传递给它,例如:

/items RequestMethod.GET 


"itemList" : [1,2,3,4,5]


Hope that helps.

【讨论】:

以上是关于您如何保护 Spring Boot / Spring-Data Rest 以便用户只能访问他自己的实体的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 中使用令牌保护 api

让 oauth2 与 spring-boot 和 rest 一起工作

将初始数据导入 Spring Boot 应用程序

Keycloak,如何保护不提供网页的 Spring Boot 后端?

使用 spring-boot OAuth2 服务器保护的 Spring-boot 应用程序

带有 Spring Boot 的 Kafka 流