我有一个User类,我想授权访问,只有用户才能看到他有权使用的内容。
使用Spring Security和Spring Data Rest可以很容易地实现这一点,我在下面的JPA Repository中做了这些 -
public interface UserRepository extends JPARepository<User,Integer> {
@PreAuthorize("hasRole('LOGGED_IN') and principal.user.id == #id")
User findOne(@Param("id") Integer id);
}
通过这种方式,用户访问Spring Data REST时可以使用支持URL,例如 -
/users/{id}
/users/{id}/userPosts
只有使用{id}登录的用户才能看到这些内容,而其他所有人都可以获得401,就像我想要的那样。
我的问题是我有一个预测,它是每个用户的公开视图,我正在使用下面的Spring Data Rest投影来创建它,我希望每个{id}
都可以访问@Projection(name = "details", types = User.class)
public interface UserDetailsProjection {
..
}
因此,即使用户已通过 /users/{id1}?projection=details
/users/{id2}?projection=details
以及{id1}
仍应提供200 OK并显示数据
我开始通过使用@PreAuthorize(&#34; permitAll&#34;)标记投影来实现这一点,但由于存储库具有更难的安全检查,因此无法工作。我们是否可以使用此功能进行投影,我们可以放松安全性?
我正在使用最新的Spring Data Rest和Spring Security发行版
答案 0 :(得分:2)
为这个用例添加自定义控制器似乎是合理的。
还请考虑:
@Value
注释User
实体拆分为两个不同的实体(配置文件,帐户),因为它们似乎具有不同的访问权限,甚至可能是操作ResourceProcessor<UserSummaryProjection>
以编程方式评估访问权限并使用DTO替换资源内容(投影)使用@Value
注释评估投影中的访问权限的示例:
@Projection(types = User.class, name = "summary")
public interface UserSummaryProjection {
@Value("#{@userSecurity.canReadEmail(target) ? target.email: null}")
String getEmail();
}
答案 1 :(得分:0)
在数据访问层中添加Spring安全代码不是一个好主意。我建议你将@PreAuthorize
注释添加到控制器/服务方法中。由于您有一个查询参数?projection=details
,因此您可以使用单独的控制器/服务方法进行详细信息投影。
在您的详细信息投影方法中添加以下内容:
@RequestMapping("/url", params = {"projection"})
@PreAuthorize("hasRole('LOGGED_IN') and principal.user.id == #id")