PreAuthorize 不适用于控制器
PreAuthorize not working on Controller
我正在尝试在方法级别定义访问规则,但它始终无法正常工作。
安全配置
@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' 没有 ROLE_ADMIN
而给我一个拒绝访问错误?
我实际上正在考虑放弃方法级别的访问规则并坚持使用 http() 蚂蚁规则,但我必须知道为什么它对我不起作用。
在控制器上使用 PrePost 注释的一个常见问题是 Spring 方法安全性基于 Spring AOP,默认情况下使用 JDK 代理实现。
这意味着它在作为接口注入控制器层的服务层上工作正常,但在控制器层上被忽略,因为控制器通常不实现接口。
以下仅代表个人意见:
- 首选方式:在服务层
上移动前置post注解
- 如果你不能(或不想),尝试让你的控制器实现一个包含所有注释方法的接口
- 作为最后一种方式,使用 proxy-target-class=true
我遇到了类似的问题,以下解决了它:
1) 我必须制定我的方法 public(即让你的方法成为 home() public)
2) 我必须使用 hasRole 而不是 hasAuthority
让它在控制器层工作。
我不得不在我的配置中添加 @EnableAspectJAutoProxy class。
示例:
@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);
}
您必须在 WebSecurityConfig 中添加 @EnableGlobalMethodSecurity(prePostEnabled = true)
。
您可以在这里找到它:http://www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
如果您有一个用于安全 bean 的 xml 上下文文件和一个用于 web/servlet 上下文的单独文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
到您的 web-context.xml/servlet 上下文。仅将其添加到安全上下文 xml.
中是不够的
它不会在子上下文中继承。
HTH
将@EnableGlobalMethodSecurity(prePostEnabled = true) 放入 MvcConfig class(扩展 WebMvcConfigurerAdapter)而不是(扩展 WebSecurityConfigurerAdapter)。
像下面的例子:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
我的控制器的方法是私有的,它们需要 public。
您的请求方法默认受保护。这样他们就可以扫描它。设置它 public!!!
我在尝试授权 AD 用户组时遇到了同样的问题
这些步骤对我有用
@EnableGlobalMethodSecurity(prePostEnabled = true) on class 用@EnableWebSecurity
注释
已创建自定义 (GroupUserDetails) UserDetails,它将具有用户名和权限以及 return 来自 custome UserDetailsService
的 GroupUserDetails 实例
用@PreAuthorize("hasAuthority('Group-Name')")注解控制器方法
我将控制器方法从私有更改为 public。它的工作。你可以试试。
我正在尝试在方法级别定义访问规则,但它始终无法正常工作。
安全配置
@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' 没有 ROLE_ADMIN
而给我一个拒绝访问错误?
我实际上正在考虑放弃方法级别的访问规则并坚持使用 http() 蚂蚁规则,但我必须知道为什么它对我不起作用。
在控制器上使用 PrePost 注释的一个常见问题是 Spring 方法安全性基于 Spring AOP,默认情况下使用 JDK 代理实现。
这意味着它在作为接口注入控制器层的服务层上工作正常,但在控制器层上被忽略,因为控制器通常不实现接口。
以下仅代表个人意见:
- 首选方式:在服务层 上移动前置post注解
- 如果你不能(或不想),尝试让你的控制器实现一个包含所有注释方法的接口
- 作为最后一种方式,使用 proxy-target-class=true
我遇到了类似的问题,以下解决了它:
1) 我必须制定我的方法 public(即让你的方法成为 home() public)
2) 我必须使用 hasRole 而不是 hasAuthority
让它在控制器层工作。 我不得不在我的配置中添加 @EnableAspectJAutoProxy class。 示例:
@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);
}
您必须在 WebSecurityConfig 中添加 @EnableGlobalMethodSecurity(prePostEnabled = true)
。
您可以在这里找到它:http://www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
如果您有一个用于安全 bean 的 xml 上下文文件和一个用于 web/servlet 上下文的单独文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
到您的 web-context.xml/servlet 上下文。仅将其添加到安全上下文 xml.
中是不够的它不会在子上下文中继承。
HTH
将@EnableGlobalMethodSecurity(prePostEnabled = true) 放入 MvcConfig class(扩展 WebMvcConfigurerAdapter)而不是(扩展 WebSecurityConfigurerAdapter)。
像下面的例子:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
我的控制器的方法是私有的,它们需要 public。
您的请求方法默认受保护。这样他们就可以扫描它。设置它 public!!!
我在尝试授权 AD 用户组时遇到了同样的问题 这些步骤对我有用
@EnableGlobalMethodSecurity(prePostEnabled = true) on class 用@EnableWebSecurity
注释已创建自定义 (GroupUserDetails) UserDetails,它将具有用户名和权限以及 return 来自 custome UserDetailsService
的 GroupUserDetails 实例用@PreAuthorize("hasAuthority('Group-Name')")注解控制器方法
我将控制器方法从私有更改为 public。它的工作。你可以试试。