Подтвердить что ты не робот

Spring Безопасность @PreAuthorize на уровне типа нельзя переопределить на уровне метода

Я пытаюсь защитить контроллер с аннотацией @PreAuthorize на уровне уровня и попытаюсь переопределить это поведение, аннотируя некоторые методы с помощью другого @PreAuthorize. Проблема, однако, заключается в том, что Spring сначала оценивает аннотацию метода (предоставляет доступ), а затем оценивает аннотацию класса (отрицает доступ).

Есть ли способ отменить этот порядок? Я еще не мог понять.

Edit:

На уровне метода я хочу предоставить доступ только к незарегистрированным пользователям:

@PreAuthorize("isAnonymous()")
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String renderCreateEntity(ModelMap model) {
    return userService.renderCreateEntity(model);
}

Стандарт для этого контроллера, однако, должен состоять в том, чтобы разрешить только полностью аутентифицированным пользователям:

@Controller
@RequestMapping(value = "/user")
@PreAuthorize("isFullyAuthenticated()")
public class UserController { [...] }

При отладке в приложении, я вижу, что сначала оценивается isAnonymous(), а затем isFullyAuthenticated(), что приводит к предоставлению права доступа и немедленному отказу в доступе.

4b9b3361

Ответ 1

Спасибо за все ваши ответы. Ответ, однако, был чем-то совершенно другим:)

Я помещаю это здесь, если у кого-то еще есть те же проблемы.

Я зарегистрировал специальный валидатор в аннотированном методе @InitBinder. Этот метод привязки называется ПОСЛЕ вызова метода, запрошенного на контроллере. И поскольку этот метод привязки не был аннотирован с помощью @PreAuthorize, запрос был отклонен.

Решение заключалось в том, чтобы аннотировать метод связывания следующим образом:

@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
    binder.setValidator(validator);
}

И затем, метод вызывает из моего OP, как ожидалось.

Ответ 2

Проблема не в том, что вам нужно изменить порядок предоставления и отклонить. Проблема проста в том, что аннотации уровня метода переопределяют аннотации уровня класса.

PrePostAnnotationSecurityMetadataSource Java Doc:

Аннотации могут быть указаны в классах или методах, и аннотации, специфичные для метода, будут иметь приоритет.

Конкретная реализация этой логики выполняется в методе findAnnotation класса PrePostAnnotationSecurityMetadataSource. (К сожалению, этот метод является конфиденциальным.)

Итак, вы можете написать свой собственный MethodSecurityMetadataSource, если вы посмотрите код PrePostAnnotationSecurityMetadataSource, вы увидите, как легко это.

Но одно предупреждение в конце: конец: сложная задача не переписывает метод, сложная задача - "вставить" новую MethodSecurityMetadataSource в систему безопасности. Я верю, что вы не можете сделать это с помощью конфигурации пространства имен безопасности spring, поэтому вам нужно заменить пространство имен безопасности spring явным объявлением bean.