Может ли 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 @Controller
s.
то, что не сработало для меня, было @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 ...")