我正在尝试在方法级别定义访问规则,但它无法正常工作。
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";
}
}
每当我尝试使用user:user
访问/ v2 / home时它执行得很好,不应该因为“用户”没有ROLE_ADMIN
而给我一个“拒绝访问”错误?
我实际上是在考虑在方法级别放弃访问规则并坚持使用http()ant规则,但我必须知道为什么它对我不起作用。
答案 0 :(得分:22)
在控制器上使用PrePost注释的一个常见问题是Spring方法安全性基于Spring AOP,默认情况下使用JDK代理实现。
这意味着它在服务层上工作正常,服务层作为接口注入控制器层,但在控制器层被忽略,因为控制器通常不实现接口。
以下是我的观点:
答案 1 :(得分:13)
您必须在WebSecurityConfig中添加@EnableGlobalMethodSecurity(prePostEnabled = true)
。
您可以在此处找到它:http://www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
答案 2 :(得分:7)
我遇到了类似的问题,以下问题解决了这个问题:
1)我必须公开我的方法(即让你的方法回家()公开)
2)我必须使用hasRole而不是hasAuthority
答案 3 :(得分:2)
使其在控制器层上工作。 我必须在我的配置类上放置@EnableAspectJAutoProxy。 示例:
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{
}
答案 4 :(得分:1)
有两种不同的方法可以使用它,一种是前缀,另一种不是。
您可以将@PreAuthorize("hasAuthority('ROLE_ADMIN')")
更改为@PreAuthorize("hasAuthority('ADMIN')")
即可。
接下来是@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);
}
答案 5 :(得分:1)
如果您的安全bean有一个xml上下文文件,而Web / servlet上下文有一个单独的XML上下文文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
到您的web-context.xml / servlet上下文。仅将其添加到安全上下文xml中是不够的。
它不在子上下文中继承。
HTH
答案 6 :(得分:0)
将@EnableGlobalMethodSecurity(prePostEnabled = true)放入MvcConfig类(扩展WebMvcConfigurerAdapter)而不是(扩展WebSecurityConfigurerAdapter)。
就像下面的例子:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
答案 7 :(得分:0)
哈哈
我也有同样的问题,那是因为我的控制器的方法是私有的...,所以它们需要公开
答案 8 :(得分:0)
您的请求方法默认受到保护。所以他们可以扫描它。设为公开!!!
答案 9 :(得分:0)
我在尝试授权用户的 AD 组时遇到了同样的问题 这些步骤对我有用
@EnableGlobalMethodSecurity(prePostEnabled = true) 在用@EnableWebSecurity 注释的类上
创建自定义(GroupUserDetails) UserDetails,它将拥有用户名和权限,并从custome UserDetailsService 返回GroupUserDetails 的实例
使用@PreAuthorize("hasAuthority('Group-Name')") 注释控制器方法