我正在构建一个显示网站数据库信息的应用程序。使用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机制可以做到这一点?
答案 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 many
和Roles
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);
}