Spring mvc 如何使@PreAuthorize具有高于@Valid或@Validated的优先级
我使用的是spring boot,我已经通过Spring mvc 如何使@PreAuthorize具有高于@Valid或@Validated的优先级,spring-mvc,spring-security,controller,bean-validation,role-base-authorization,Spring Mvc,Spring Security,Controller,Bean Validation,Role Base Authorization,我使用的是spring boot,我已经通过 @EnableGlobalMethodSecurity(prePostEnabled = true, order = Ordered.HIGHEST_PRECEDENCE) 下面是我的控制器代码 @PreAuthorize("hasAnyRole('admin') or principal.id == id") @RequestMapping(value = "/{id}", method = RequestMethod.PUT) public
@EnableGlobalMethodSecurity(prePostEnabled = true, order = Ordered.HIGHEST_PRECEDENCE)
下面是我的控制器代码
@PreAuthorize("hasAnyRole('admin') or principal.id == id")
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public User updateUser(@PathVariable("id") String id, @Valid @RequestBody UserDto userDto)
{ ....}
但是,当非管理员用户尝试执行PUT请求时,JSR303验证程序将在@PreAuthorize之前启动。
例如,非管理员用户最终得到的结果是“需要名字”而不是“拒绝访问”。但在用户提供第一个name变量以通过验证程序后,返回了拒绝访问
有人知道如何在@Valid或@Validated之前执行@PreAuthorize-get-check吗
为了执行一些复杂的规则检查,我必须使用这种方法级授权,而不是基于url的授权。对于相同的场景,我发现了通过spring筛选器实现安全性的建议。
下面是类似的帖子: 另外,可能还有一种不同的方法-尝试通过在@InitBinder中注册自定义验证器来使用验证(从而跳过@valid注释) 要访问筛选器类中的主体对象,请执行以下操作:
SecurityContextImpl sci = (SecurityContextImpl)
session().getAttribute("SPRING_SECURITY_CONTEXT");
if (sci != null) {
UserDetails cud = (UserDetails) sci.getAuthentication().getPrincipal();
}
在本例中,/{id}是URL中的路径参数。要访问筛选器或侦听器类中的路径参数,请执行以下操作:
String[] requestMappingParams = ((HandlerMethod)handler).getMethodAnnotation(RequestMapping.class).params()
for (String value : requestMappingParams) {.
我也有同样的问题,我找到了这篇文章。戴纳姆先生的评论帮助我了解出了什么问题 以下是我所做的:
@RequestMapping(method = RequestMethod.POST)
@PreAuthorize("hasRole('MY_ROLE')")
public ResponseEntity createNewMessage(@RequestBody CreateMessageDTO createMessageDTO) {
// The user is authorized
return createNewMessageWithValidation(createMessageDTO);
}
private ResponseEntity createNewMessageWithValidation(@Valid CreateMessageDTO createMessageDTO) {
// The DTO is valid
return ...
}
使用
websecurityConfigureAdapter.configure(HttpSecurity http)
而不是@PreAuthorize
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers( "/path/**").hasRole("admin");
}
}
谢谢,我也看到了那篇文章,但是spring过滤器(基于url)在我的案例中不起作用,因为我需要使用url参数对主体ID进行验证。我在实现中使用了@InitBinder,但在验证程序之前仍然没有调用@PreAuthorize。您可以访问servlet筛选器中的主体对象。这有帮助吗?我在servlet筛选器类中添加了一个访问prinicipal对象的代码段。我不确定这是否会让您更容易…谢谢,我以前从未使用过servlet fitler。假设我的一个REST PUT请求是/user/{id},我只允许用户编辑自己的帐户。如何检查筛选器中的{id}?例如,用户id=2只允许对/user/2而不是/user/3发出PUT请求?哦,我明白了。好的,我添加了一些代码,说明如何从请求对象访问path param/{id}。我想这会奏效的。希望有帮助!这永远不会发生。只有在执行方法时才会调用
@PreAuthorize
。但是,@Valid
是在准备执行方法时处理的,这发生在方法实际执行之前。所以这行不通。作为一种解决方法,您可以进行手动验证,而不是依赖@Valid
注释。我明白了。感谢您在后台解释它是如何工作的。我认为,如果他们将来能够在预授权后支持验证,那将是一件好事。这将很困难,因为这将改变AOP的整个工作方式:)。我可以看到映射URL和增加安全性的改进。目前只使用了ant风格的表达式和正则表达式,但是我可以看到人们可能也希望使用路径变量来实现安全性。有没有干净的解决方案?