Spring 数据休息:基于安全的投影
Spring Data Rest: Security based projection
我正在使用 Spring Data Rest and Spring Data JPA 的当前版本并且有以下实体:
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private String email;
...getter/setter methods...
}
我也在用Spring Security
.
我的用户存储库:
@RepositoryRestResource(
collectionResourceRel = "user",
path = "user",
excerptProjection = UserSimpleProjection.class)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
例如:
- 用户 1 已登录
- 用户 1 请求
http://localhost:8080/user/1
- 所有字段都可见
- 用户 1 请求
http://localhost:8080/user/2
- 只有 id
和 name
可见。
我尝试了 Jackson 的不同解决方案,none 解决了我的问题:
- JsonView 的使用:我找不到办法,根据登录的用户
更改 ObjectMapper
的视图
- 如 here 所述实施了不同的 Jackson 过滤器,但我发现无法针对不同的请求更改
ObjectMapper
配置。
然后我找到了Projections。
我创建了一个投影:
@Projection(name = "simple", types = User.class)
public interface UserSimpleProjection {
public Long getId();
public String getName();
}
还有一个详细的:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
public String getEmail();
}
到目前为止一切顺利,根据我的要求得到不同的结果。
有没有办法根据Spring安全性自动切换投影and/or限制不同角色的不同投影?
不,Spring 数据 REST 投影不支持此功能。
您可以将 "virtual" 值 属性 添加到调用带有安全检查的服务方法的投影中:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
@Value("#{@userService.checkAccess(target)? target.email : null}")
public String getEmail();
}
您的自定义 UserService
组件将 return true
如果电子邮件应该公开或者只是 @PreAuthorize
在 checkAccess(..)
上抛出 AccessDeniedException
什么对你更好。
请注意,SpEL 中的 target
属性 包含原始对象 - 由 Spring-DATA 提供。
您也可以在 Spring 安全配置中使用 RegexRequestMatcher 来完成此操作,如下所示:
.regexMatchers(HttpMethod.GET,"/user/.*projection=simple.*").hasRole("ROLE_ADMIN")
我正在使用 Spring Data Rest and Spring Data JPA 的当前版本并且有以下实体:
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private String email;
...getter/setter methods...
}
我也在用Spring Security
.
我的用户存储库:
@RepositoryRestResource(
collectionResourceRel = "user",
path = "user",
excerptProjection = UserSimpleProjection.class)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
例如:
- 用户 1 已登录
- 用户 1 请求
http://localhost:8080/user/1
- 所有字段都可见 - 用户 1 请求
http://localhost:8080/user/2
- 只有id
和name
可见。
我尝试了 Jackson 的不同解决方案,none 解决了我的问题:
- JsonView 的使用:我找不到办法,根据登录的用户 更改
- 如 here 所述实施了不同的 Jackson 过滤器,但我发现无法针对不同的请求更改
ObjectMapper
配置。
ObjectMapper
的视图
然后我找到了Projections。
我创建了一个投影:
@Projection(name = "simple", types = User.class)
public interface UserSimpleProjection {
public Long getId();
public String getName();
}
还有一个详细的:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
public String getEmail();
}
到目前为止一切顺利,根据我的要求得到不同的结果。
有没有办法根据Spring安全性自动切换投影and/or限制不同角色的不同投影?
不,Spring 数据 REST 投影不支持此功能。
您可以将 "virtual" 值 属性 添加到调用带有安全检查的服务方法的投影中:
@Projection(name = "detailed", types = User.class)
public interface UserDetailProjection extends UserSimpleProjection{
@Value("#{@userService.checkAccess(target)? target.email : null}")
public String getEmail();
}
您的自定义 UserService
组件将 return true
如果电子邮件应该公开或者只是 @PreAuthorize
在 checkAccess(..)
上抛出 AccessDeniedException
什么对你更好。
请注意,SpEL 中的 target
属性 包含原始对象 - 由 Spring-DATA 提供。
您也可以在 Spring 安全配置中使用 RegexRequestMatcher 来完成此操作,如下所示:
.regexMatchers(HttpMethod.GET,"/user/.*projection=simple.*").hasRole("ROLE_ADMIN")