我试图在方法级别定义访问规则,但它不起作用。
安全配置
@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 规则,但我必须知道为什么它对我不起作用。
您必须在 WebSecurityConfig 中添加
@EnableGlobalMethodSecurity(prePostEnabled = true)
。
您可以在这里找到它:http://www.baeldung.com/spring-security-expressions-basic
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
在控制器上使用 PrePost 注解的一个常见问题是 Spring 方法安全性基于 Spring AOP,默认情况下使用 JDK 代理实现。
这意味着它在服务层上工作得很好,作为接口注入到控制器层中,但在控制器层上它被忽略,因为控制器通常不实现接口。
以下只是我的意见:
将
@EnableGlobalMethodSecurity(prePostEnabled = true)
放入MvcConfig类(扩展WebMvcConfigurerAdapter)而不是(扩展WebSecurityConfigurerAdapter)。
就像下面的例子:-
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MvcConfiguration extends WebMvcConfigurerAdapter {
我遇到了类似的问题,以下解决了它:
1)我必须公开我的方法(即公开你的方法 home())
2)我必须使用 hasRole 而不是 hasAuthority
对于 2023 年及以后来到这里的人,您必须将
@EnableMethodSecurity
注解添加到您的配置类中。还值得注意的是,自 2023 年起,Spring Boot 还使用自动配置。下面包含一个示例安全配置。
@Configuration
@EnableWebSecurity
@EnableMethodSecurity // Add this
public class SecurityConfig {
// Add your configuration Beans here
}
你的控制器应该看起来像这样:
@RestController
@RequestMapping("/users")
public class UserController
{
// Replace this with your service or other means to fetch resources
private final UserRepository userRepository;
public UserController(UserRepository userRepository)
{
this.userRepository = userRepository;
}
// Note: I am using a scope called "users.read" below, but you can use
// ROLE_<role_name> if you are using roles instead.
@GetMapping(value = "/list")
@PreAuthorize("hasAuthority('users.read')")
public List<UserDto> listUsers()
{
return userRepository.findAllBy();
}
}
有两种不同的使用方法,一种是加前缀,一种不加前缀。 也许你把
@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);
}
我在尝试授权用户的 AD 组时遇到了同样的问题 这些步骤对我有用
@EnableGlobalMethodSecurity(prePostEnabled = true)
标注有 @EnableWebSecurity
的课程
创建了自定义(GroupUserDetails)UserDetails,它将具有用户名和权限,并从自定义 UserDetailsService 返回 GroupUserDetails 的实例
用
注释控制器方法@PreAuthorize("hasAuthority('Group-Name')")
我的控制器的方法是私有的,他们需要公开。
使其在控制器层工作。 我必须将
@EnableAspectJAutoProxy
放在我的配置类上。
示例:
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy
@ComponentScan(basePackages = { "com.abc.fraud.ts.userservices.web.controller" })
public class WebConfig extends WebMvcConfigurerAdapter{
}
如果您的安全 Bean 有一个 xml 上下文文件,并且有一个单独的 Web/Servlet 上下文文件,那么您还需要添加:
<security:global-method-security pre-post-annotations="enabled"/>
您的 web-context.xml / servlet 上下文。仅仅将其添加到安全上下文 xml 中是不够的。
它不会在子上下文中继承。
HTH
我将控制器方法从
private
更改为 public
并且它正在工作。
您的请求方式默认为
protected
。所以他们无法扫描它。设置一下public
2023 年 6 月:
对于那些仍在挣扎的人:
安全配置
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder){
UserDetails user = User.withUsername("user")
.password(passwordEncoder.encode("user123"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(admin,user);
}
你的控制器应该是这样的:
@GetMapping("/getAll")
@PreAuthorize("hasAuthority('ROLE_USER')")
public List<Student> findAllStudents() {
return studentServiceI.findAll();
}
我在方法中有一个 static 关键字,通过删除它,@Preauthorize 起作用了。
您应该在 HttpSecurity 对象的authorizeRequest 中添加
.anyRequest().authenticated
。
因为默认的 HttpBuilder 实现仍然处于活动状态,并且因为它在 Web 请求过滤器链期间进行评估,所以它具有优先权。
通过
authorizeRequest.anyRequest().authenticated
,您所做的是使用 SecurityConfig 类显式允许主端点上的所有请求,同时要求在所有其他端点上进行身份验证。这为您的应用程序设置了总体最低身份验证要求。您还重新启用了基于表单的身份验证。