Spring security Spring安全性:hasAuthority、hasRole和预授权不起作用
我正在尝试测试使用标准Spring安全注释和方法保护的web api。 我查看了网站上的所有选项,没有任何帮助,下面是代码。没有角色,一切都很好。我已经为这个问题痛苦了好几天。我会感谢你的帮助,谢谢Spring security Spring安全性:hasAuthority、hasRole和预授权不起作用,spring-security,Spring Security,我正在尝试测试使用标准Spring安全注释和方法保护的web api。 我查看了网站上的所有选项,没有任何帮助,下面是代码。没有角色,一切都很好。我已经为这个问题痛苦了好几天。我会感谢你的帮助,谢谢 @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) publ
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImp userDetailsService;
@Autowired
JwtFilter jwtFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/authenticate").permitAll()
.antMatchers(HttpMethod.GET,"/userData").permitAll()
.antMatchers(HttpMethod.GET,"/allUsers").hasAuthority("ROLE_ADMIN")
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint())
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
控制器类
@RestController
public class AuthenticationController {
@Autowired
public AuthenticationManager authenticationManager;
@Autowired
private UserDetailsServiceImp userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserRepository userRepository;
@RequestMapping(value = "/userData", method = RequestMethod.GET)
public String hello(){
return "Hello new User";
}
@RequestMapping(value = "/allUsers", method = RequestMethod.GET)
public List<UserD> findAll(){
return userRepository.findAll();
}
@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest jwtRequest) throws Exception{
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(jwtRequest.getName(), jwtRequest.getPassword()));
}catch(BadCredentialsException e){
throw new Exception("Incorrect username and password", e);
}
final UserD userD = (UserD)userDetailsService.loadUserByUsername(jwtRequest.getName());
final String token = jwtUtil.generateToken(userD.getName(), userD.getRole());
Map<Object, Object> model = new HashMap<>();
model.put("username", jwtRequest.getName());
model.put("token", token);
return ResponseEntity.ok(model);
}
}
以及添加角色的用户数据
@Component
public class DataInitializer implements CommandLineRunner {
@Autowired
UserRepository userRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public void run(String... args) throws Exception {
UserD user = new UserD();
user.setName("user");
user.setPassword(passwordEncoder.encode("password"));
user.setRole("ROLE_USER");
userRepository.save(user);
UserD admin = new UserD();
admin.setName("admin");
admin.setPassword(passwordEncoder.encode("password"));
admin.setRole("ROLE_ADMIN");
userRepository.save(admin);
}
}
这是数据库返回的内容
我想先澄清一点,这可能有助于您准确定位问题: UserDetailsServiceImp是否从数据库、LDAP或其他存储库检索用户名和角色? 从数据库、LDAP或其他存储库检索什么角色? 它是否已经有前缀“ROLE_u” 如果从数据库中检索到的角色是“ADMIN”,则在调用hasAuthority()时,不能自行添加角色 如果不是这样,请在日志中启用调试,以查看/allUsers请求到底发生了什么
更新: 我怀疑的一件事是你实现了UserDetailsServiceImp 您必须确保已将角色设置为“用户详细信息”。 在您的实现中,您似乎直接从DB查询,不确定是否将角色设置为userDetails
return userRepository.findByName(username).get(0);
以下是它应该发生的事情:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//assume, there is only one user with the username
UserD user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
List<GrantedAuthority> roles = new ArrayList<>();
//assume, there is only one role for the user
roles.add(new SimpleGrantedAuthority(user.getRole()));
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
roles);
}
@覆盖
public UserDetails loadUserByUsername(字符串用户名)引发UsernameNotFoundException{
//假设只有一个用户名为的用户
UserD user=userRepository.findByUsername(用户名);
if(user==null){
抛出新的UsernameNotFoundException(“找不到用户名为:+username的用户”);
}
列表角色=新的ArrayList();
//假设用户只有一个角色
添加(新的SimpleGrantedAuthority(user.getRole());
返回新的org.springframework.security.core.userdetails.User(User.getUsername(),User.getPassword(),
角色);
}
我认为您的UserDetailsServiceImp实现可能存在问题,请确保它在“loadUserByUsername”方法中将授予的权限设置到用户中。我还更新了答案,以显示如何设置授予的权限。我添加了一个屏幕截图
return userRepository.findByName(username).get(0);
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//assume, there is only one user with the username
UserD user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
List<GrantedAuthority> roles = new ArrayList<>();
//assume, there is only one role for the user
roles.add(new SimpleGrantedAuthority(user.getRole()));
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
roles);
}