spring PreAuthorize 不适用于控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32442408/
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
PreAuthorize not working on Controller
提问by prettyvoid
I'm trying to define access rules at method-level but it's not working what so ever.
我正在尝试在方法级别定义访问规则,但它不起作用。
SecurityConfiguration
安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
withUser("user").password("user").roles("USER").and().
withUser("admin").password("admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/v2/**").authenticated()
.and()
.httpBasic()
.realmName("Secure api")
.and()
.csrf()
.disable();
}
}
ExampleController
示例控制器
@EnableAutoConfiguration
@RestController
@RequestMapping({"/v2/"})
public class ExampleController {
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@RequestMapping(value = "/home", method = RequestMethod.GET)
String home() {
return "Hello World";
}
}
Whenever I try to access /v2/home using user:user
it executes just fine, shouldn't it give me an Access Denied error due to 'user' not having ROLE_ADMIN
?
每当我尝试使用user:user
它访问 /v2/home 时,它执行得很好,难道它不应该因为“用户”没有而给我一个访问被拒绝的错误ROLE_ADMIN
?
I'm actually thinking of ditching access rules at method-level and stick to http() ant rules, but I have to know why it's not working for me.
我实际上正在考虑在方法级别放弃访问规则并坚持 http() 蚂蚁规则,但我必须知道为什么它对我不起作用。
采纳答案by Serge Ballesta
A common problem with using PrePost annotations on controllers is that Spring method security is based on Spring AOP, which is by default implemented with JDK proxies.
在控制器上使用 PrePost 注释的一个常见问题是 Spring 方法安全性基于 Spring AOP,默认情况下使用 JDK 代理实现。
That means that it works fine on the service layer which is injected in controller layer as interfaces, but it is ignored on controller layer because controller generally do not implement interfaces.
这意味着它在作为接口注入控制器层的服务层上工作正常,但它在控制器层被忽略,因为控制器通常不实现接口。
The following is just my opinion:
以下只是我的看法:
- prefered way: move the pre post annotation on service layer
- if you cannot (or do not want to), try to have your controller implement an interface containing all the annotated methods
- as a last way, use proxy-target-class=true
- 首选方式:在服务层上移动 pre post 注释
- 如果您不能(或不想),请尝试让您的控制器实现一个包含所有带注释方法的接口
- 最后一种方法,使用proxy-target-class=true
回答by Eric Zürcher
You have to add @EnableGlobalMethodSecurity(prePostEnabled = true)
in your WebSecurityConfig.
您必须添加@EnableGlobalMethodSecurity(prePostEnabled = true)
您的 WebSecurityConfig。
You can find it here: http://www.baeldung.com/spring-security-expressions-basic
你可以在这里找到它:http: //www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
回答by Horowitzathome
I had a similar problem and the following solved it:
我有一个类似的问题,以下解决了它:
1) I had to make my method public (i.e. make your method home() public)
1)我必须公开我的方法(即公开你的方法 home())
2) I have to use hasRole instead of hasAuthority
2)我必须使用 hasRole 而不是 hasAuthority
回答by stanicmail
put @EnableGlobalMethodSecurity(prePostEnabled = true) into MvcConfig class (extends WebMvcConfigurerAdapter) instead of (extends WebSecurityConfigurerAdapter).
将 @EnableGlobalMethodSecurity(prePostEnabled = true) 放入 MvcConfig 类(扩展 WebMvcConfigurerAdapter)而不是(扩展 WebSecurityConfigurerAdapter)。
Like below example:-
像下面的例子:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
回答by beautifulcode
There are two different ways to use this, one is to prefix and one is not.
And you maybe change @PreAuthorize("hasAuthority('ROLE_ADMIN')")
to @PreAuthorize("hasAuthority('ADMIN')")
will be ok.
有两种不同的使用方式,一种是前缀,一种不是。你也许更改@PreAuthorize("hasAuthority('ROLE_ADMIN')")
到@PreAuthorize("hasAuthority('ADMIN')")
都会好的。
next is @PreAuthorize
source code.
接下来是@PreAuthorize
源代码。
private String defaultRolePrefix = "ROLE_";
public final boolean hasAuthority(String authority) {
return hasAnyAuthority(authority);
}
public final boolean hasAnyAuthority(String... authorities) {
return hasAnyAuthorityName(null, authorities);
}
public final boolean hasRole(String role) {
return hasAnyRole(role);
}
public final boolean hasAnyRole(String... roles) {
return hasAnyAuthorityName(defaultRolePrefix, roles);
}
回答by kripal kashyav
For making it working on controller layer. I had to put @EnableAspectJAutoProxy on my configuration class. Example :
使其在控制器层上工作。我不得不将 @EnableAspectJAutoProxy 放在我的配置类上。例子 :
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{
}
回答by Georgi Peev
Hah,
哈,
I had the same proble and it was ,because my Controller`s methods were private ... ,they need to be public
我有同样的问题,因为我的控制器的方法是私有的......,它们需要是公开的
回答by Chris
If you have a xml context file for your security beans and a separate one for your web/servlet context, than you als need to add:
如果您的安全 bean 有一个 xml 上下文文件,而您的 web/servlet 上下文有一个单独的上下文文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
to your web-context.xml / servlet context. Its not enough to just add it in the security context xml.
到您的 web-context.xml / servlet 上下文。仅将其添加到安全上下文 xml 中是不够的。
Its not inherited in child contexts.
它不会在子上下文中继承。
HTH
HTH