我使用具有安全性的 Spring WebController。 当用户拥有或已经获得某些权限时,我想将某些值屏蔽为 NULL。 我将 JpaRepository.findAll 与规范一起使用。 所以基本上我想在 Criteriabuild 中添加一些逻辑以返回列的一些自定义默认值。
1,代码1 2、代码2
我想用规范来实现这个查询: 选择 ID,“默认”作为代码 来自代码表
提前致谢!
当用户拥有或已经获得某些权限时
如果您尝试在
SecurityContext
中隐藏当前已验证对象的某些值,您应该利用 MethodAuthorizationDeniedHandler
和 @AuthorizeReturnObject
注释。
首先创建将处理结果的自定义注释
@Retention(RetentionPolicy.RUNTIME)
@PostAuthorize("true")
@AuthorizeReturnObject
@interface PostReadProtect {}
然后使用存储库中的规范参数覆盖方法
interface FooRepository extends JpaRepository<Foo, Long>, JpaSpecificationExecutor<Foo> {
@Override
@PostReadProtect
List<Foo> findAll(Specification<Foo> specification);
}
创建我之前提到的处理程序
@Component
class ProtectedHandler implements MethodAuthorizationDeniedHandler {
@Override
public Object handleDeniedInvocation(
MethodInvocation methodInvocation,
AuthorizationResult authorizationResult) {
return "[PROTECTED]";
}
}
并保护您实体中的字段
@Getter
@Setter
@Entity
class Foo {
@Id
@GeneratedValue
private Long id;
private String col1;
@PreAuthorize("false")
@HandleAuthorizationDenied(handlerClass = ProtectedHandler.class)
public String getCol1() {
return col1;
}
}
您可以按照习惯在
Pre/PostAuthorize
注释中使用任何 Spring 表达式。因此,在我们的 @PostAuthorize("true")
示例中,我们允许任何人调用 findAll(spec)
,但是通过 getter 访问 col1
将触发 AccessDeniedException
,因为 @PreAuthorize("false")
由 ProtectedHandler
处理,然后运行您的代码。因为一切都由 Spring Security 处理,所以它为您提供了很多选项,如何根据当前情况自定义逻辑 Authentication
final var e = new Foo();
e.setCol1("password");
fooRepository.save(e);
final var ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(new UsernamePasswordAuthenticationToken("fake", "login"));
SecurityContextHolder.setContext(ctx);
final var res = fooRepository.findAll((r, cq, cb) -> cb.le(r.get("id"), 500L));
// outputs [PROTECTED] even we saved it with "password" value
System.out.println(res.getFirst().getCol1());
或者,您可以使用
AuthorizationAdvisorProxyFactory
类手动管理整个过程。