Может ли Spring Security использовать @PreAuthorize для методов контроллеров Spring? - PullRequest
70 голосов
/ 21 июня 2010

Может ли Spring Security использовать @PreAuthorize в методах контроллеров Spring?

Ответы [ 7 ]

68 голосов
/ 21 июня 2010

Да, работает нормально.

Вам нужно <security:global-method-security pre-post-annotations="enabled" /> в ...-servlet.xml.Также требуется CGLIB-прокси , поэтому либо у ваших контроллеров не должно быть интерфейсов, либо вы должны использовать proxy-target-class = true.

23 голосов
/ 05 июля 2012

См. FAQ по безопасности Spring (выделено мной).

В веб-приложении Spring контекст приложения, который содержит компоненты Spring MVC для сервлета диспетчера, часто отделен отосновной контекст приложения.Он часто определяется в файле myapp-servlet.xml, где «myapp» - это имя, назначенное Spring DispatcherServlet в web.xml.Приложение может иметь несколько DispatcherServlets, каждый со своим собственным изолированным контекстом приложения.Бины в этих «дочерних» контекстах не видны остальной части приложения.«Родительский» контекст приложения загружается с помощью ContextLoaderListener, который вы определили в своем файле web.xml, и видим для всех дочерних контекстов.Этот родительский контекст обычно используется для определения конфигурации безопасности, включая элемент).В результате любые ограничения безопасности, применяемые к методам в этих веб-компонентах, не будут применены, поскольку компоненты не могут быть видны из контекста DispatcherServlet.Вам нужно либо переместить объявление в веб-контекст, либо переместить бины, которые вы хотите защитить, в основной контекст приложения.

Обычно мы рекомендуем применять метод защиты на уровне службы, а не на отдельных веб-контроллерах..

Если вы применяете pointcut для сервисного слоя, вам нужно только установить <global-method-security> в контексте безопасности вашего приложения.

17 голосов
/ 25 сентября 2012

Если вы используете Spring 3.1, вы можете сделать несколько довольно крутых вещей с этим. Взгляните на https://github.com/mohchi/spring-security-request-mapping. Это пример проекта, который интегрирует @PreAuthorize с RequestMappingHandlerMapping Spring MVC, так что вы можете сделать что-то вроде:

@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String authenticatedHomePage() {
    return "authenticatedHomePage";
}

@RequestMapping("/")
public String homePage() {
    return "homePage";
}

Запрос «/» вызовет authenticatedHomePage (), если пользователь аутентифицирован. В противном случае он вызовет homePage ().

9 голосов
/ 26 декабря 2014

Прошло более двух лет с тех пор, как этот вопрос был задан, но из-за проблем, с которыми я столкнулся сегодня, я бы предпочел не использовать @Secured, @PreAuthorize и т. Д. На @Controller с.

Что мне не помогло, так это @Validated в сочетании с @Secured контроллером:

@Controller
@Secured("ROLE_ADMIN")
public class AdministrationController {

// @InitBinder here...

@RequestMapping(value = "/administration/add-product", method = RequestMethod.POST)
public String addProductPost(@ModelAttribute("product") @Validated ProductDto product, BindingResult bindingResult) {
    // ...
}

Validator просто не запускается (Spring MVC 4.1.2, Spring Security 3.2.5) и проверки не выполняются.

Подобные проблемы вызваны прокси-серверами CGLIB, используемыми Spring (когда класс не реализует интерфейс, Spring создает прокси CGLIB; если класс реализует какой-либо интерфейс, генерируется прокси JDK - документация , хорошо объяснено здесь и здесь ).

Как упомянуто в ответах, которые я связал выше, не лучше использовать аннотации Spring Security на сервисном уровне, который обычно реализует интерфейсы (поэтому используются прокси JDK), поскольку это не приводит к таким проблемам.

Если вы хотите защитить веб-контроллеры, лучше использовать <http> и <intercept-url />, которые привязаны к конкретным URL-адресам, а не к методам в контроллерах и работают довольно хорошо. В моем случае:

<http use-expressions="true" disable-url-rewriting="true">

    ...

    <intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')" />

</http>
5 голосов
/ 03 сентября 2017

Уже есть ответ относительно того, как заставить это работать, изменяя конфигурацию xml; однако, если вы работаете с конфигурацией на основе кода, вы можете добиться того же, разместив следующую аннотацию над классом @Configuration:

@EnableGlobalMethodSecurity(prePostEnabled=true)
1 голос
/ 13 августа 2016

Чтобы расширить ответ, предоставленный Энди, вы можете использовать:

@PreAuthorize("hasRole('foo')")

для проверки конкретной роли.

0 голосов
/ 20 августа 2018

Сначала вам нужно добавить эту аннотацию в свой WebSecurityConfig для включения аннотаций @Pre и @Post.

    @EnableGlobalMethodSecurity(prePostEnabled = true)

Вы также можете проверить роли / полномочия следующим образом

    @PreAuthorize("hasAuthority('ROLE_ADMIN')")

эквивалентна

    @PreAuthorize("hasRole('ROLE_ADMIN')")

Вы также можете проверить несколько ролей / полномочий следующим образом

    @PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER') or ...")
...