Spring 预授权不在控制器上工作

Spring 预授权不在控制器上工作,spring,spring-security,spring-boot,spring-java-config,Spring,Spring Security,Spring Boot,Spring Java Config,我试图在方法级别定义访问规则,但它从来都不起作用 证券配置 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override public void configure(AuthenticationManager

我试图在方法级别定义访问规则,但它从来都不起作用

证券配置

@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();
    }
}
示例控制器

@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时,它执行得很好,难道不应该因为“user”没有
角色\u ADMIN
而给我一个拒绝访问错误吗


实际上,我正在考虑放弃方法级别的访问规则,坚持http()ant规则,但我必须知道为什么它对我不起作用。

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

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

以下是我的看法:

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

我遇到了一个类似的问题,以下方法解决了这个问题:

1) 我必须公开我的方法(即公开你的方法home())


2) 我必须使用hasRole而不是hasAuthority,以使其在控制器层上工作。 我必须在我的配置类中添加@enableAspectProxy。 例如:

@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{

}

有两种不同的方法使用它,一种是前缀,另一种不是。 您可能会将
@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);
}

您必须在Web安全配置中添加
@EnableGlobalMethodSecurity(prespenabled=true)

你可以在这里找到它:


如果安全bean有一个xml上下文文件,web/servlet上下文有一个单独的xml上下文文件,则需要添加:

<security:global-method-security pre-post-annotations="enabled"/>

到您的web-context.xml/servlet上下文。仅仅将其添加到安全上下文xml中是不够的

它不是在子上下文中继承的


HTH

将@EnableGlobalMethodSecurity(prespenabled=true)放入MvcConfig类(扩展WebMVCConfigureAdapter)而不是(扩展WebSecurityConfigureAdapter)

如以下示例所示:-

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {

我的控制器的方法是私有的,它们需要是公共的。

默认情况下,您的请求方法受到保护。所以他们可以扫描它。把它公之于众

我在尝试授权用户的广告组时遇到了同样的问题 这些步骤对我有效

  • @在用@EnableWebSecurity注释的类上启用GlobalMethodSecurity(prespenabled=true)

  • 已创建自定义(GroupUserDetails)UserDetails,它将具有用户名和权限,并从custome UserDetails服务返回GroupUserDetails实例

  • 用@PreAuthorize(“hasAuthority('Group-Name'))注释控制器方法



  • 谢谢你的回答。我尝试在
    crudepository
    界面上使用注释,效果很好。在我看来,每个控制器都有一个接口是有点愚蠢的,因为接口并不是真的必要
    proxy target class=true
    没有什么区别,注释在控制器上仍然不起作用,但是当注释位于存储库接口(不能子类com.sun.proxy)内时,它会导致崩溃(设置为true)。无论如何,我想我会坚持安全配置中的规则,可能会在我的一些存储库中使用预授权。我注意到的另一件事是,我看到过一些示例,其中@PreAuthorize在
    类中使用,而不是在
    接口中使用,并且它应该可以工作。。我想知道为什么它对他们有效,但对我无效。在应用程序上下文中启用Aop添加接口为我修复了它,但另一个项目没有接口,并且控制器方法受到保护。他们一定在使用其他配置,而我没有。我在控制器上使用@PreAuthorize时遇到了奇怪的问题:有些应用程序工作正常,有些应用程序不正常。我遇到了同样的问题,将方法公开解决了!把控制器的方法公之于众为我解决了。天哪!这是如此简单,为什么在Java中调试这些东西如此困难??感谢您将方法从私有更改为公共对我很有效。并且应该添加此源代码,我的控制器在何处以及如何访问它?ExampleController的问题是,仅将角色\u ADMIN更改为ADMIN。我尝试了您建议的方法,但实现
    hasRole
    子句(如
    @PreAuthorize)的正确方法是什么(“hasRole('ADMIN')”
    我的工作没有这个@enableSpectjautoproxy,我刚才使用了@PreAuthorize(“hasAuthority('ADMIN')”)这是为什么?@kripal kashyavAlso根据之前的评论,如果将pre/post放在一个不实现接口的控制器方法上,也会将注释属性
    proxyTargetClass=true
    添加到
    EnableGlobalMethodSecurity
    中,不幸的是,这对我不起作用(请参阅)。它已经使用
    @EnableGlobalMethodSecurity了吗(prespenabled=true)
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class MvcConfiguration extends WebMvcConfigurerAdapter {