我使用的是Sping Boot 2.7.2,并为我的用户设置了角色和权限的安全配置。但是,在访问控制表达式中混合角色和权限时遇到了问题。
以下是我的配置:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().access("isAuthenticated() and hasAuthority('read')")
.and()
.build();
}
@Bean
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager udm = new InMemoryUserDetailsManager();
UserDetails ud = User.withUsername("bill")
.password(passwordEncoder().encode("password"))
.authorities("read")
.roles("MANAGER")
.build();
UserDetails ud1 = User.withUsername("john")
.password(passwordEncoder().encode("password"))
.authorities("write")
.roles("ADMIN")
.build();
udm.createUser(ud);
udm.createUser(ud1);
return udm;
}
使用此配置,当尝试访问端点时,两个用户都被拒绝。但是,如果我删除角色并在创建用户时仅使用权限,则可以正常工作:Bill可以访问端点,而John不能。
使用此配置,它将按预期工作:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().access("isAuthenticated() and hasAuthority('read')")
.and()
.build();
}
@Bean
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager udm = new InMemoryUserDetailsManager();
UserDetails ud = User.withUsername("bill")
.password(passwordEncoder().encode("password"))
.authorities("read")
.build();
UserDetails ud1 = User.withUsername("john")
.password(passwordEncoder().encode("password"))
.authorities("write")
.build();
udm.createUser(ud);
udm.createUser(ud1);
return udm;
}
我想了解为什么在混合使用角色和权限时会出现此问题,以及如何在配置中同时使用角色和权限。如有任何帮助或建议,我将不胜感激。
1条答案
按热度按时间neekobn81#
问题是
User
的构造。如果你已经检查了
User
的代码,或者更确切地说,UserBuilder
和相应的authorities
和roles
方法,你会看到每个方法都取代了完整的权限。所以你可以使用其中一个。如果你看得更仔细,你会发现
authorities
和roles
实际上都是authorities
。唯一的区别是roles
的前缀是ROLE_
。因此,在初始设置中,您最终只有一个名为
ROLE_MANAGER
/ROLE_ADMIN
的权限,而不是您的read
权限。不需要同时调用这两个方法,只需同时调用
read
和ROLE_MANAGER
。