如何保护 RepositoryRestController

How to secure RepositoryRestController

假设我有 2 个实体:

@Entity
public class Post {
    @NotEmpty
    private String title;
    @NotEmpty
    @Lob
    private String html;
    @NotEmpty
    @Lob
    private String text;
    @ManyToOne
    private Topic topic;
    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "content_media", joinColumns = {@JoinColumn(name = "content_id")}, inverseJoinColumns = {@JoinColumn(name = "media_id")})
    private Set<Media> medias = new HashSet<>();
    @CreatedBy
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn
    private User createdBy;

    @LastModifiedBy
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn
    private User lastModifiedBy;
    ...
}
@Entity
public class Media {
    @NotEmpty
    private String localPath;
    @NotEmpty
    private String fileName;
    private long fileLength;
    private String fileType;
    private int focusPointX;
    private int focusPointY;
    ...
}

我使用以下方式公开它们:

@RepositoryRestController
public interface MediaRepository extends JpaRepository<Media, Long> {
}
@RepositoryRestController
public interface PostRepository extends JpaRepository<Post, Long> {
}

我希望这些控制器是安全的。让我自己解释一下。

有没有办法使用 RepositoryRestController 和 Spring 安全性或 RepositoryRestController 仅用于 public 资源,我应该使用 RestController 自己编写服务层?

是的,您可以直接将 Spring 安全与 Spring 数据 REST 结合使用。您需要使用 Spring 安全配置来定义路由的安全性,如下所示:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {

    http.httpBasic().and().authorizeRequests().
        antMatchers(HttpMethod.POST, "/posts").hasRole("USER").
        antMatchers(HttpMethod.DELETE, "/posts/**").hasRole("ADMIN").and().
        csrf().disable();
  }
}

存储库方法将使用 Spring 安全注释进行保护。例如

@RepositoryRestController
public interface PostRepository extends JpaRepository<Post, Long> {
    @Override
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    void delete(Long aLong);
}

上面的代码只是一个指针。您可以根据需要自定义它。 Here is the link to Spring Data examples repository.

更新 要处理由创建的用户或 ADMIN_ROLE 中的任何用户对 post 的更新,您需要创建一个控制器 class 并定义一个方法来处理更新

@RequestMapping(method={RequestMethod.PUT}, value={"posts/{id}"})
public void updatePost(@PathVariable("id") Long id, HttpServletRequest request)
{
    //Fetch the authenticated user name
    SecurityContext securityContext = SecurityContextHolder.getContext();
    Authentication authentication = securityContext.getAuthentication();
    Object principal = authentication.getPrincipal();

    if (principal instanceof UserDetails) {
        username = ((UserDetails) principal).getUsername();
    }

    // Make a database call to verify if the user is owner of the post
    Post post = postRepository.getPostByUserName(String username, Long postId);

    if (post == null && !request.isUserInRole("ADMIN");) {
        //return 403 error code
    }

    //proceed with the update
}