如何授权Spring应用程序的服务层?

时间:2015-04-02 10:35:54

标签: java spring spring-mvc spring-security

我正在构建一个显示网站数据库信息的应用程序。使用Spring Security保护应用程序,我的用户可以拥有不同的角色。应根据当前用户的角色显示记录。例如,我想显示数据库中的书籍。角色X也只能看到一些图书和角色Y。但是角色ADMIN可以看到所有图书。

现在我想知道授权在何处以及如何发生。我认为服务层是一个好地方,但我如何查询当前用户可以访问的书籍。

我的表格如下:

book (id, name)
role (id, name)
role_book (id, role_id, book_id)

因此,对书籍的查询将是SELECT b.id, b.name FROM book b, role r role_book rb WHERE b.id = rb.book_id AND r.id = rb.role_id AND r.name IN (<roles of the current user>)。当前用户具有ADMIN角色时,我只需选择数据库中的所有图书。

但是如何在Spring服务方法中执行这些查询?我认为这是一项常见的授权任务。是否有任何Spring机制可以做到这一点?

3 个答案:

答案 0 :(得分:3)

我会做一个简单的重新设计,这也将使数据层更可重用。就像这样。

服务层

这里我们采用当前用户的角色并传递给数据层。

Iterable<Book> findAllMyBooks(){
...
    List<String> roles = new ArrayList<>();
    Authentication authentication = SecurityContextHolder.getContext()getAuthentication();
    for (GrantedAuthority auth : authentication.getAuthorities()) {
        roles.add(auth.getAuthority());
    }
    bookRepository.findAllByRoles(roles);
...
}

数据层

根据角色查询图书。因此,您可以使用此功能稍后在管理面板中为未登录的用户提取图书。

请注意,我没有时间检查JPQL查询。 'ADMIN' IN (:roles)中可能存在错误。请检查一下。

@Query("SELECT b FROM Book b INNER JOIN b.roles r WHERE r.name IN (:roles) OR 'ADMIN' IN (:roles)")
Iterable<Book> findAllByRoles(@Param("roles") List<String> roles);

实体模型

Many to manyRoles

建立Books关系

答案 1 :(得分:1)

对于方法授权,您可以使用@PreAuthorize("hasRole('ROLE_USER')")

方法顶部的

注释,这里是关于主题的链接: http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

要检查用户的角色,您还可以使用

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

在Spring Security 3.0中

答案 2 :(得分:1)

Spring Security 4现在有Spring Data集成:http://docs.spring.io/spring-security/site/docs/current-SNAPSHOT/reference/htmlsingle/#data

在Spring Data资源库中:

@Repository
public interface FooRepository extends PagingAndSortingRepository<Foo,Long> {
    @Query("select f from Foo f where f.owner.id = ?#{ principal?.id }")
    Page<Foo> find(Pageable pageable);
}