我正在开发 Spring Boot Security 项目,我在一些端点上进行了身份验证,以防止用户访问,并在我点击此 URL 时向 ADMIN 授予权限:admin/users。我得到了登录页面,我输入了凭据,而不是返回它返回的实际内容:
类型=禁止,状态=403
这是我的安全配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// inject spring user details interface
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/api/**" , "/").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin();
}
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
}
管理员用户控制器:
@RestController
@RequestMapping("admin/users")
public class UserController {
//
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
// get all users
@PreAuthorize("hasAnyRole('ADMIN')")
@GetMapping
public List<User> getAllUsers(){
return userRepository.findAll();
}
// test
@PreAuthorize("hasAnyRole('ADMIN')")
@GetMapping("/test")
public String message() {
return "secured end point";
}
//create new users
@PreAuthorize("hasAnyRole('ADMIN')")
@PostMapping
public User registerUser(@RequestBody User user){
String password = user.getPassword();
String encodedPassword = passwordEncoder.encode(password);
user.setPassword(encodedPassword);
return userRepository.save(user);
}
}
用户详细信息:
public class CustomUserDetails implements UserDetails {
/**
*
*/
private static final long serialVersionUID = 1256711395932122675L;
private User user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return true;
}
}
用户详细信息服务:
[![@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
CustomUserDetail userDetail = null;
if(user != null) {
userDetail = new CustomUserDetail();
userDetail.setUser(user);
}
else {
throw new UsernameNotFoundException("user not exist with username " + username);
}
System.out.println("user details" + userDetail);
return userDetail;
}
}][2]][2]
我通过简单地更正 getAuthorities() 解决了这个问题,我删除了
simpleGrantedAuthority()
中的“ROLE_”,将返回值提取到 userDetail.java 中的变量中,并使用 hasAuthority()
而不是 hasRole()
。
收到 403 错误的代码 - 禁止:
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
}
解决方案:
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = user.getRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getRole()))
.collect(Collectors.toList());
return authorities;
}