有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何配置SpringDataRest,使其只返回登录用户拥有的数据

我正在开发一个Spring Boot RESTful应用程序,它将为web应用程序公开一系列API,以便对资源执行CRUD操作

我正在使用spring-data-rest(当然还有spring-data-jpa)在Spring Magic的帮助下公开实体/存储库

尽管我已经用spring security保护了(基于角色的)端点,但它并不是完全安全的

例如: 我有一个User实体,它与Carone-to-many关系。因此,获取用户汽车的端点(由spring-data-rest自动公开)是localhost:8080/users/{userId}/cars

但是,任何具有所需角色的用户都可以通过另一个用户的userId访问端点。 我想要的行为是以一种方式保护这些端点,如果我登录用户的ID是1,那么我们只能点击localhost:8080/users/1/cars。与任何其他userId的任何其他请求都应该以403或其他形式结束

注意:我知道如果我写自己的控制器,那么我就可以掌握校长,做我想做的事。我只是想知道spring-data-rest中有没有一种方法或模式可以实现这一点


共 (2) 个答案

  1. # 1 楼答案

    要实现这一点,您需要编写一个Interceptor。它将在以下情况下使用:

    1. 在向控制器发送请求之前

    2. 在向客户发送响应之前

    在编写任何Interceptor之前,它应该实现HandlerInterceptor接口。 支持的三种方法是:

    1. preHandle()方法− 在发送请求之前执行操作 到controller。此方法应返回true以返回 回复客户
    2. postHandle()方法− 用于在发送前执行操作 对客户的回应
    3. afterCompletion()方法− 这用于执行操作 完成请求和响应后

    代码:

        @Component
        public class MyInterceptor implements HandlerInterceptor {
           @Override
           public boolean preHandle(
              HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
           String pathVariablesMap = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); 
          //From this pathVariablesMap  extract UserId and match with a loggedinUserId
           }
           @Override
           public void postHandle(
              HttpServletRequest request, HttpServletResponse response, Object handler, 
             ) throws Exception {}
    
           @Override
           public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
              Object handler, Exception exception) throws Exception {}
        }
    

    通过使用InterceptorRegistry,您可以注册Interceptors,如下所示:

    @Component
    public class MyRegistoryConfig extends WebMvcConfigurer{
       @Autowired
       MyInterceptor myInterceptor ;
    
       @Override
       public void addInterceptors(InterceptorRegistry registry) {
          registry.addInterceptor(myInterceptor );
       }
    }
    

    有关更多信息,请点击以下链接Interceptors

    编辑:正如@Ritesh建议的那样,他补充了这一点

  2. # 2 楼答案

    由于您已经使用Spring安全性保护了应用程序,下面是另一个使用Method Security Expressions

    请查看@Pre and @Post Annotations以了解您的要求

    1. 您可以将登录用户的用户ID存储到身份验证对象。详情here

    2. 用@PreAuthorize注释保护所需的方法,如下所示

      @PreAuthorize("#user.userId == authentication.principal.userId")
      public List<Car> getCars(User user){..}
      

    请记住启用方法安全性

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {..}