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

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

7 ответов


Да, он отлично работает.

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


посмотреть весенняя безопасность FAQ (выделено мной).

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

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

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


Если вы используете 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().


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

то, что не сработало для меня, было @Validated в сочетании с :

@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) {
    // ...
}

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

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

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

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

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

    ...

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

</http>

уже есть ответ о том, как заставить его работать, изменив конфигурацию xml; однако, если вы работаете с конфигурацией на основе кода, Вы можете достичь того же, поместив следующую аннотацию поверх вашего @Configuration класс:

@EnableGlobalMethodSecurity(prePostEnabled=true)

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

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

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


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

    @EnableGlobalMethodSecurity(prePostEnabled = true)

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

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

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

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

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

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