我有一个Spring MVC应用程序,它提供了一个视图,显示了来自Customer
实体的所有字段,例如姓名,地址,电话号码等。该应用程序具有各种角色,例如ROLE_USER
和ROLE_ADMIN
。 ROLE_USER
的用户只能看到客户名称,ROLE_ADMIN
的用户可以看到所有客户字段。
目前我实施此功能的方式是使用Thymeleaf视图,该视图使用SpringSecurityDialect根据用户的角色限制对某些字段的访问:
<th:block sec:authorize="hasRole('ROLE_ADMIN')">
<div th:text="${customer.phoneNumber}" />
</th:block>
虽然这种方法非常好,但感觉不对,而且难以测试。我想针对控制器编写测试,控制器使用具有不同角色的主体调用控制器方法,例如testViewCustomerAsRoleAdmin
和testViewCustomerAsRoleUser
。当控制器将Customer
返回到完全填充并且每个字段都可通过getter访问的视图时,无法进行验证。
我所追求的是实体级别的某种字段级安全性,我可以使用Spring Security注释:
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getPhoneNumber()
{
return phoneNumber;
}
如果在未经授权的情况下尝试访问该字段时,如果这可能会引发AccessDeniedException
,那将是理想的。
Jersey项目似乎有这样一个概念,提到了here,here和一个例子here。但它似乎仅限于基于角色的安全性,而不是@PreAuthorize
有没有办法或使用Spring Security实现此类事情,我知道安全上下文或SpEL评估上下文在实体中不可用,因为它们不是Spring管理的。如果没有,是否有其他方法可以让我实现同样的目标?
修改
我完全不了解Spring Security框架,但似乎可以在ApectJ模式下使用Spring AOP来完成域(实体)类的方法。这将是获取AccessDecisionManager
并传递身份验证(可能从SecurityContextHolder
获得)以及域类方法(如果存在)上的注释内容的情况。有没有人有做这种事的经验?
答案 0 :(得分:2)
我设法在AspectJ模式下使用Spring AOP解决了这个问题。如果您启用AspectJ模式并执行编译时或编译加载时,各种Spring注释(例如<a></a>
和<li><a href=''>List item</a></li> //Do not delete
<li><a href=''></a></li> //Delete
)将适用于任何非Spring托管类,这里有一个非常好的示例:{ {3}}
您需要确保项目中具有@Transactional
依赖项(如果您正在使用编译时编织,则需要插件)以启用@PreAuthorize
注释的编织。尽管spring-security-aspects
中的评论将该类描述为:
使用Spring Security @Secured注释的具体AspectJ方面 JDK 1.5 +。
该类确实编织了其他Spring注释,包括@Secured
,AnnotationSecurityAspect
,@PreAuthorize
和@PreFilter
。