Spring Security,Method Security annotation(@Secured)无效(java config)
我正在尝试使用@Secured(“ADMIN”)设置方法安全注释(没有任何XML,只有java配置,Spring Boot)。 但是通过角色访问不起作用。
安全配置:
@Configuration @EnableWebSecurity public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{ ..... @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/api/**").fullyAuthenticated().and() .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); } ..... }
我想限制访问控制器的方法:
@RestController @RequestMapping("/api/groups") public class GroupController { @Autowired private GroupService groupService; @Secured("ADMIN") @RequestMapping public List list() { return groupService.findAll(); } }
通过url限制访问是有效的,具有:
.antMatchers("/api/**").hasAuthority("ADMIN")
也许我忘了指定我想要按角色限制?
UPD:根据规则,在Controller层或Service层中哪一层必须是@PreAuthorize("hasRole('ADMIN')")
?
请加上这个
@EnableGlobalMethodSecurity(securedEnabled = true)
此元素用于在应用程序中启用基于注释的安全性(通过在元素上设置适当的属性),还可以将安全性切入点声明组合在一起,这些声明将专门针对@Secured
应用于整个应用程序上下文。 因此,您的代码应如下所示
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
控制器上的哪种方法安全性不起作用可能有很多原因。
首先是因为它从未在Spring Security手册中作为示例引用…开玩笑但是将Spring工具放在他们不想去的地方可能会很棘手。
更严重的是,您应该启用@Mudassar已经说过的方法安全性。 手册说:
我们可以在任何@Configuration
实例上使用@EnableGlobalMethodSecurity
批注启用基于注释的安全性。 例如,以下内容将启用Spring Security的@Secured
注释。
@Configuration @EnableGlobalMethodSecurity(securedEnabled = true) public class MethodSecurityConfig { // ... }
请注意,Mudassar的答案是正确的,直到这里。
但方法安全性基于AOP,默认情况下在接口上使用JDK代理。 这就是为什么所有示例都在服务层上应用方法安全性的原因,因为服务类通常作为接口注入控制器。
您当然可以在控制器层上使用它,但是:
- 要么所有的控制器都为你所有的
@Secured
注释方法实现接口 - 或者你必须切换到类代理
我试图遵循的规则是:
- 如果我想保护URL,我坚持使用HTTPSecurity
- 如果我需要允许更细粒度的访问,我在服务层添加安全性
我知道这个post很老了,我的答案暗示了这个post中不同人的部分答案; 但这里列出了陷阱和答案的列表:
- 使用@Secured时,角色名称是(例如)ADMIN; 这意味着@Secured(“ROLE_ADMIN”)的注释。
- WebSecurityConfigurerAdapter必须具有@EnableGlobalMethodSecurity(securedEnabled = true)
- 与大多数与Spring相关的代理一样,请确保类和安全方法不是最终的。 对于Kotlin来说,这意味着“打开”每个方法以及课程。
- 当类及其方法是虚拟的(“打开”)时,则不存在对接口的隐含需求。
以下是Kotlin工作示例的一部分:
@RestController @RequestMapping("api/v1") open class DiagnosticsController { @Autowired lateinit var systemDao : SystemDao @RequestMapping("ping", method = arrayOf(RequestMethod.GET)) @Secured("ROLE_ADMIN") open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ... }
和
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) open class WebSecurityConfig : WebSecurityConfigurerAdapter() {
问候
这个问题已经解决了。
我添加@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{ }
在控制器中我将@Secured("ADMIN")
更改为@PreAuthorize("hasRole('ADMIN')")
也许您应该将AppSecurityConfiguration注册到与WebMvcConfig相同的上下文(扩展WebMvcConfigurerAdapter)。
AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext(); mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
您需要使用@secured(ROLE_ADMIN)而不是@secured(ADMIN)。 您需要在角色名称前面写上“ROLE_” 。 请查看下面提到的示例,确保只有具有Admin角色的用户才能访问list()方法。
@RestController @RequestMapping("/api/groups") public class GroupController { @Autowired private GroupService groupService; @Secured("ROLE_ADMIN") @RequestMapping public List list() { return groupService.findAll(); } }