PreAuthorize不在Controller上工作

时间:2015-09-07 15:57:14

标签: spring spring-security spring-boot spring-java-config

我正在尝试在方法级别定义访问规则,但它无法正常工作。

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规则,但我必须知道为什么它对我不起作用。

10 个答案:

答案 0 :(得分:22)

在控制器上使用PrePost注释的一个常见问题是Spring方法安全性基于Spring AOP,默认情况下使用JDK代理实现。

这意味着它在服务层上工作正常,服务层作为接口注入控制器层,但在控制器层被忽略,因为控制器通常不实现接口。

以下是我的观点:

  • 首选方式:在服务层上移动帖子前注释
  • 如果您不能(或不想),请尝试让您的控制器实现包含所有带注释方法的界面
  • 作为最后一种方式,使用 proxy-target-class = true

答案 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 组时遇到了同样的问题 这些步骤对我有用

  1. @EnableGlobalMethodSecurity(prePostEnabled = true) 在用@EnableWebSecurity 注释的类上

  2. 创建自定义(GroupUserDetails) UserDetails,它将拥有用户名和权限,并从custome UserDetailsS​​ervice 返回GroupUserDetails 的实例

  3. 使用@PreAuthorize("hasAuthority('Group-Name')") 注释控制器方法