16

私はスプリング ブートを使用しており、WebSecurityConfigurerAdapter でグローバル メソッド セキュリティを有効にしています。

@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 リクエストを実行しようとすると、@PreAuthorize の前に JSR303 バリデーターが作動します。たとえば、管理者以外のユーザーは、「アクセスが拒否されました」ではなく「名が必要です」などのメッセージを受け取りました。しかし、ユーザーがバリデータを渡すために最初の名前変数を指定した後、アクセス拒否が返されました。

@Valid または @Validated の前に @PreAuthorize を強制的にチェックする方法を知っている人はいますか?

また、複雑なルール チェックを実行するには、URL ベースの承認ではなく、この種のメソッド レベルの承認を使用する必要があります。

4

3 に答える 3

3

私は同じ問題を抱えていて、この投稿を見つけました。M. Deinum のコメントは、何がうまくいかなかったのかを理解するのに役立ちます

これが私がしたことです:

  1. public メソッドには @PreAuthorize があり、チェックを行います
  2. @RequestBody パラメーターに @Valid はありませ
  3. DTO 検証を行う2 つ目のメソッド private を作成します。@Valid アノテーションの使用
  4. パブリック メソッドは、呼び出しをプライベート メソッドに委譲します。プライベート メソッドは、パブリック メソッドが承認されている場合にのみ呼び出されます

例 :

@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 ...
}
于 2016-08-26T12:08:44.507 に答える