Java Spring Security 可以在 Spring 控制器方法上使用 @PreAuthorize 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3087548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can Spring Security use @PreAuthorize on Spring controllers methods?
提问by egervari
Can Spring Security use @PreAuthorize
on Spring controllers methods?
Spring Security 可以@PreAuthorize
在 Spring 控制器方法上使用吗?
采纳答案by axtavt
Yes, it works fine.
是的,它工作正常。
You need <security:global-method-security pre-post-annotations="enabled" />
in ...-servlet.xml
. It also requires CGLIB proxies, so either your controllers shouldn't have interfaces, or you should use proxy-target-class = true
.
你需要<security:global-method-security pre-post-annotations="enabled" />
在...-servlet.xml
. 它还需要CGLIB 代理,所以你的控制器不应该有接口,或者你应该使用proxy-target-class = true
.
回答by Tomasz
See Spring Security FAQ(emphasis mine).
请参阅Spring Security 常见问题解答(强调我的)。
In a Spring web application, the application context which holds the Spring MVC beans for the dispatcher servlet is often separate from the main application context. It is often defined in a file called myapp-servlet.xml, where “myapp” is the name assigned to the Spring DispatcherServlet in web.xml. An application can have multiple DispatcherServlets, each with its own isolated application context. The beans in these “child” contexts are not visible to the rest of the application. The “parent” application context is loaded by the ContextLoaderListener you define in your web.xml and is visible to all the child contexts. This parent context is usually where you define your security configuration, including the element). As a result any security constraints applied to methods in these web beans will not be enforced, since the beans cannot be seen from the DispatcherServlet context. You need to either move the declaration to the web context or moved the beans you want secured into the main application context.
Generally we would recommend applying method security at the service layer rather than on individual web controllers.
在 Spring Web 应用程序中,为调度程序 servlet 保存 Spring MVC bean 的应用程序上下文通常与主应用程序上下文分开。它通常在名为 myapp-servlet.xml 的文件中定义,其中“myapp”是分配给 web.xml 中 Spring DispatcherServlet 的名称。一个应用程序可以有多个 DispatcherServlets,每个都有自己独立的应用程序上下文。这些“子”上下文中的 bean 对应用程序的其余部分不可见。“父”应用程序上下文由您在 web.xml 中定义的 ContextLoaderListener 加载,并且对所有子上下文可见。此父上下文通常是您定义安全配置(包括元素)的位置。因此,将不会强制执行应用于这些 Web bean 中的方法的任何安全约束,因为无法从 DispatcherServlet 上下文中看到 bean。您需要将声明移动到 Web 上下文或将您想要保护的 bean 移动到主应用程序上下文中。
通常,我们建议在服务层而不是在单个 Web 控制器上应用方法安全性。
If you apply pointcuts to service layer you only need to set <global-method-security>
in your app's security context.
如果将切入点应用于服务层,则只需<global-method-security>
在应用程序的安全上下文中进行设置。
回答by andy
If you're using Spring 3.1, you can do some pretty cool stuff with this. Take a look at https://github.com/mohchi/spring-security-request-mapping. It's a sample project that integrates @PreAuthorize with Spring MVC's RequestMappingHandlerMapping so that you can do something like:
如果你使用的是 Spring 3.1,你可以用它做一些很酷的事情。看看https://github.com/mohchi/spring-security-request-mapping。这是一个示例项目,将 @PreAuthorize 与 Spring MVC 的 RequestMappingHandlerMapping 集成在一起,以便您可以执行以下操作:
@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String authenticatedHomePage() {
return "authenticatedHomePage";
}
@RequestMapping("/")
public String homePage() {
return "homePage";
}
A request for "/" will call authenticatedHomePage() if the user is authenticated. Otherwise it will call homePage().
如果用户已通过身份验证,则对“/”的请求将调用 authenticatedHomePage()。否则它将调用 homePage()。
回答by dominik
It's over two years since this question was asked but because of problems I had today I'd rather discourage using @Secured
, @PreAuthorize
, etc. on @Controller
s.
这是两年多以来,这一问题被提出,但由于问题,我今天我宁愿反对使用@Secured
,@PreAuthorize
等上@Controller
秒。
What didn't work for me was @Validated
combined with @Secured
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 simply does not fire (Spring MVC 4.1.2, Spring Security 3.2.5) and no checks are performed.
Validator 不会触发(Spring MVC 4.1.2,Spring Security 3.2.5)并且不执行任何检查。
Similar problems are caused by CGLIB proxies used by Spring (when there is no interface implemented by a class, Spring creates CGLIB proxy; if the class implements any interface then JDK Proxy is generated - documentation, well explained hereand here).
类似的问题是由 Spring 使用的 CGLIB 代理引起的(当没有类实现的接口时,Spring 创建 CGLIB 代理;如果类实现了任何接口,则生成 JDK 代理 -文档,在这里和这里都有很好的解释)。
As mentioned in the answers that I linked above, is't better to use Spring Security annotations on service layer that usually implements interfaces (so JDK Proxies are used) as this does not lead to such problems.
正如我在上面链接的答案中提到的,在通常实现接口的服务层上使用 Spring Security 注释(因此使用 JDK 代理)并不是更好,因为这不会导致此类问题。
If you want to secure web controllers, the better idea is to use <http>
and <intercept-url />
that are bound to specific urls rather than methods in controllers and work pretty well. In my case:
如果你想保护 web 控制器,更好的主意是使用<http>
和<intercept-url />
绑定到特定的 url 而不是控制器中的方法并且工作得很好。就我而言:
<http use-expressions="true" disable-url-rewriting="true">
...
<intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')" />
</http>
回答by Atul
To Extend the answer provided by Andy, you can use:
要扩展安迪提供的答案,您可以使用:
@PreAuthorize("hasRole('foo')")
to check the specific role.
检查具体的作用。
回答by OlgaMaciaszek
There is already a reply regarding how to make it work by changing xml configuration; however, if you are working with code-based configuration, you can achieve the same by placing the following annotation over your @Configuration
class:
已经有关于如何通过更改 xml 配置使其工作的回复;但是,如果您正在使用基于代码的配置,则可以通过在@Configuration
类上放置以下注释来实现相同的效果:
@EnableGlobalMethodSecurity(prePostEnabled=true)
回答by Siddhey Sankhe
First you need to add this annotation in your WebSecurityConfig to enable @Pre and @Post annotations.
首先,您需要在 WebSecurityConfig 中添加此注释以启用 @Pre 和 @Post 注释。
@EnableGlobalMethodSecurity(prePostEnabled = true)
You can also check roles/authorities as follows
您还可以按如下方式检查角色/权限
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
equivalent to
相当于
@PreAuthorize("hasRole('ROLE_ADMIN')")
You can also check multiple roles/authorities as follows
您还可以按如下方式检查多个角色/权限
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER') or ...")