预授权不适用于控制器
Posted
技术标签:
【中文标题】预授权不适用于控制器【英文标题】:PreAuthorize not working on Controller 【发布时间】:2015-12-03 05:31:29 【问题描述】:我正在尝试在方法级别定义访问规则,但它并没有像以前那样工作。
安全配置
@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 时,它执行得很好,它不应该因为“用户”没有 ROLE_ADMIN
而给我一个访问被拒绝错误吗?
我实际上正在考虑在方法级别放弃访问规则并坚持 http() ant 规则,但我必须知道为什么它不适合我。
【问题讨论】:
【参考方案1】:我将控制器方法从私有更改为公共。它的工作。你可以试试。
【讨论】:
【参考方案2】:我在尝试授权用户的 AD 组时遇到了同样的问题 这些步骤对我有用
@EnableGlobalMethodSecurity(prePostEnabled = true) 在使用 @EnableWebSecurity 注释的类上
创建了自定义(GroupUserDetails)UserDetails,它将具有用户名和权限,并从自定义 UserDetailsService 返回 GroupUserDetails 的实例
使用 @PreAuthorize("hasAuthority('Group-Name')") 注释控制器方法
【讨论】:
【参考方案3】:我的 Controller 的方法是私有的,它们需要公开。
【讨论】:
我在过去一个月里一直在尝试这个,一切都是正确的,期待这个公开的..地狱般的学习。终于发现问题了。谢谢@georgi Peev【参考方案4】:您的请求方法默认受到保护。所以他们可以扫描它。公开!!!
【讨论】:
【参考方案5】:将@EnableGlobalMethodSecurity(prePostEnabled = true) 放入MvcConfig 类(扩展WebMvcConfigurerAdapter)而不是(扩展WebSecurityConfigurerAdapter)。
如下例:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter
【讨论】:
【参考方案6】:如果您的安全 bean 有一个 xml 上下文文件,而您的 web/servlet 上下文有一个单独的文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
到您的 web-context.xml / servlet 上下文。仅将其添加到安全上下文 xml 中是不够的。
它不会在子上下文中继承。
HTH
【讨论】:
OP 已经使用@EnableGlobalMethodSecurity(prePostEnabled = true)
【参考方案7】:
您必须在 WebSecurityConfig 中添加 @EnableGlobalMethodSecurity(prePostEnabled = true)
。
你可以在这里找到它:http://www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
【讨论】:
同样根据之前的评论者,如果将 pre/post 放在不实现接口的控制器方法上,还将注释属性proxyTargetClass = true
添加到 EnableGlobalMethodSecurity
不幸的是,这对我不起作用(请参阅***.com/questions/53125388/…)。【参考方案8】:
有两种不同的使用方式,一种是前缀,一种不是。
你也许把@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);
【讨论】:
并且这个源应该被添加到我的控制器在哪里以及如何访问它? ExampleController的问题,只是把ROLE_ADMIN改成了ADMIN 我按照您的建议进行了尝试,效果很好,但是实现hasRole
子句(如@PreAuthorize("hasRole('ADMIN')")
)的正确方法是什么【参考方案9】:
为了让它在控制器层上工作。 我不得不将@EnableAspectJAutoProxy 放在我的配置类中。 示例:
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.abc.fraud.ts.userservices.web.controller" )
public class WebConfig extends WebMvcConfigurerAdapter
【讨论】:
我的工作没有这个@EnableAspectJAutoProxy 我只是使用了@PreAuthorize("hasAuthority('ADMIN')") 这是为什么呢? @kripal kashyav【参考方案10】:我遇到了类似的问题,以下解决了它:
1) 我必须公开我的方法(即公开你的方法 home())
2) 我必须使用 hasRole 而不是 hasAuthority
【讨论】:
我遇到了同样的问题,公开方法解决了! 公开控制器方法为我解决了这个问题。 将方法从私有更改为公共对我有用。【参考方案11】:在控制器上使用 PrePost 注释的一个常见问题是 Spring 方法安全性基于 Spring AOP,默认情况下使用 JDK 代理实现。
这意味着它在作为接口注入控制器层的服务层上可以正常工作,但在控制器层上它被忽略了,因为控制器通常不实现接口。
以下只是我的看法:
首选方式:将前置注解移到服务层 如果您不能(或不想),请尝试让您的控制器实现一个包含所有注释方法的接口 作为最后一种方式,使用 proxy-target-class=true【讨论】:
感谢您的回答。我试过在CrudRepository
接口上使用注释,它工作得很好。在我看来,每个控制器都有一个接口有点愚蠢,因为接口并不是真正必要的。 proxy-target-class=true
没有区别,注释在控制器上仍然不起作用,但是当在存储库接口(不能子类 com.sun.proxy)中有注释时,它会导致崩溃(当设置为 true 时)。无论如何,我想我会坚持安全配置中的规则,并且可能在我的一些存储库上使用 PreAuth。
我注意到的另一件事是,我看到了在 class
而不是 interface
中使用 @PreAuthorize 的示例,它应该可以工作。我想知道它为什么有效适合他们,但不适合我。
在应用程序上下文中启用 Aop
我在 Controller 上使用 @PreAuthorize 时遇到了奇怪的问题:一些应用程序运行良好,而一些应用程序则不行。
现在已经改变了吗?因为 prePost 注释在我的控制器上工作得非常好,无需实现任何接口或允许目标类代理以上是关于预授权不适用于控制器的主要内容,如果未能解决你的问题,请参考以下文章
Spring MVC 预授权控制器操作未收到 POST 请求
Axios 发布请求适用于 Postman,但不适用于浏览器(它返回“错误 401-未授权”)
UINavigationController 不适用于 SearchDisplay 控制器