복붙노트

[SPRING] 컨트롤러에서 유효성 검사 (@Valid) 전에 보안 액세스 (@Secured 또는 @PreAuthorize)를 확인하는 방법은 무엇입니까?

SPRING

컨트롤러에서 유효성 검사 (@Valid) 전에 보안 액세스 (@Secured 또는 @PreAuthorize)를 확인하는 방법은 무엇입니까?

여기 내 컨트롤러 코드 :

@PreAuthorize("hasRole('CREATE_USER')")
@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public UserReturnRO createUser(@Valid @RequestBody UserRO userRO) throws BadParameterException{

    return userService.createUser(userRO);
}

내 역할은 적절한 역할이없는 클라이언트가 사용자를 만들려고 할 때 컨트롤러가 보낸 데이터가 유효하지 않더라도 "승인되지 않음"으로 응답하는 것입니다. 그 대신 클라이언트가 적절한 역할이 없으면 잘못된 데이터로 사용자를 생성하려고 할 때 컨트롤러가 @Valid 메시지 (예 : "암호는 비워 둘 수 없음")로 응답하고 "승인되지 않은" .

PreAuthorized Interface에서이 문장을 찾을 수 있습니다 :

그러나 그것이 사실이 아닌 것처럼 보입니다.

해결법

  1. ==============================

    1.@Valid는 실제 메서드 호출 전에 처리되고 @PreAuthorize보다 먼저 처리되므로이 작업은 직접 수행 할 수 없습니다.

    @Valid는 실제 메서드 호출 전에 처리되고 @PreAuthorize보다 먼저 처리되므로이 작업은 직접 수행 할 수 없습니다.

    하지만 대신 할 수있는 일은 BindingResult를 모델 (userRO) 바로 다음에 삽입하고 그로부터 유효성 검사 프로세스를 제어하는 ​​것입니다. 그런 다음 BindingResult에 몇 가지 오류가 있는지 확인하고 잘못된 요청 응답을 반환하는지 확인합니다 (스프링과 유사).

    예:

    @ResponseBody
    @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @PreAuthorize("hasRole('CREATE_USER')")
    public ResponseEntity<?> createUser(@RequestBody @Valid UserRO userRO, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseEntity.badRequest().body(result.getAllErrors());
        }
        return ResponseEntity.ok(userService.createUser(userRO));
    }
    
  2. ==============================

    2.이미 언급했듯이, Spring Security의 @PreAuthorize는 메소드 advice이며, 메소드와 메소드의 인수가 이미 해결 될 때까지 참여하지 않는다는 것을 의미합니다.

    이미 언급했듯이, Spring Security의 @PreAuthorize는 메소드 advice이며, 메소드와 메소드의 인수가 이미 해결 될 때까지 참여하지 않는다는 것을 의미합니다.

    이미 주어진 대답과는 별도로, 인수를 해결하기 전에 권한을 이전 할 수있는 몇 가지 방법이 있습니다.

    먼저, Spring Security는 요청이 메소드에 매핑되기 전에 URL을 검사합니다. 그리고 이것은 @Controller이기 때문에 대신 @PreAuthorize 대신 해당 레벨의 요청에 요청을 매핑 할 수 있다고 가정하는 것이 합리적입니다.

    http
        .authorizeRequests()
            .mvcMatchers(POST, "/somepath").hasRole("CREATE_USER")
    

    둘째, Spring MVC는 메서드 인수를 파싱하기 전에 권한을 확인하는 데 제한된 지원을 제공합니다. 예를 들어 다음과 같이 할 수 있습니다.

    @EnableWebMvc
    public static class MvcConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            UserRoleAuthorizationInterceptor userRole =
                new UserRoleAuthorizationInterceptor();
            userRole.setAuthorizedRoles("CREATE_USER");
            registry.addInterceptor(userRole);
        }
    }
    

    @PreAuthorize는 글로벌 설정이기 때문에 @PreAuthorize보다 훨씬 기본이지만 완벽을 기하기 위해 포함 시켰습니다.

    세 번째 (경고, 일부 무능함), 독자적인 HandlerInterceptor를 생성 할 수 있습니다.

    흐름은 다음과 같습니다.

    따라서 HandlerInterceptor는 인수가 해결되기 전에 검사합니다. 그러나 MethodSecurityInterceptor만큼이나 복잡하지는 않습니다. 예를 들면 다음과 같습니다.

    static class AuthorizationInterceptor extends HandlerInterceptorAdapter {
        SecurityMetadataSource securityMetadataSource;
        AccessDecisionManager accessDecisionManager;
    
        @Override
        public void preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) {
    
            Authentication authenticated = (Authentication) request.getUserPrincipal();
            MethodInvocation mi = convert(handler);
            Collection<ConfigAttribute> attributes =
                this.securityMetadataSource.getAttributes(mi);
    
            // throws AccessDeniedException
            this.accessDecisionManager.decide(authenticated, mi, attributes);
            return true;
        }
    }
    

    그런 다음 함께 연결하십시오.

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    static class MethodConfig extends GlobalMethodSecurityConfiguration {
        @Bean
        HandlerInterceptor preAuthorize() throws Exception {
            return new AuthorizationInterceptor(
                accessDecisionManager(), methodSecurityMetadataSource());
        }
    }
    
    @EnableWebMvc
    public static class MvcConfig implements WebMvcConfigurer {
        @Autowired
        AuthorizationInterceptor authorizationInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(authorizationInterceptor);
        }
    }
    

    MethodSecurityInterceptor가 승인 된 요청에 여전히 참여할 것이기 때문에 이는 상상할 수 없습니다.

  3. from https://stackoverflow.com/questions/22780668/how-to-check-security-acess-secured-or-preauthorize-before-validation-vali by cc-by-sa and MIT license