//我的第一个答案中的问题解决方案。
我简化了一个简单的Spring Security项目,并且似乎做得正确,因为我之前做过,而且几乎可以使用相同的代码来完成所有工作,但是现在我无法通过“ / auth / login”进行请求。
有趣的是,它在配置类http.antMatchers('/ auth / **“)。permitAll中,但是我只能通过/ auth / reg路径访问/ auth / login-返回401。
也许有人熟悉这个问题,很乐意帮助我解决这个问题。
我的安全配置类:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private UserDetailsServiceImpl userDetailsService;
private JwtEntryPoint entryPoint;
@Autowired
public WebSecurityConfig(UserDetailsServiceImpl userDetailsService,
JwtEntryPoint entryPoint) {
this.userDetailsService = userDetailsService;
this.entryPoint = entryPoint;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(entryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public JwtTokenFilter jwtTokenFilter() {
return new JwtTokenFilter();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
RestController:
@RestController
@RequestMapping("/auth")
public class AuthController {
private AuthenticationManager authManager;
private UserRepository userRepository;
private RoleRepository roleRepository;
private PasswordEncoder encoder;
private JwtTokenProvider tokenProvider;
@Autowired
public AuthController(AuthenticationManager authManager,
UserRepository userRepository,
RoleRepository roleRepository,
PasswordEncoder encoder,
JwtTokenProvider provider) {
this.authManager = authManager;
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.encoder = encoder;
this.tokenProvider = provider;
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginForm loginForm) {
Authentication authentication = authManager.authenticate(
new UsernamePasswordAuthenticationToken(loginForm.getUsername(), loginForm.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = tokenProvider.generateJwtToken(authentication);
UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
return ResponseEntity.ok(new JwtResponse(token, userPrincipal.getUsername(), userPrincipal.getAuthorities()));
}
@PostMapping("/reg")
public ResponseEntity<?> register(@ModelAttribute RegForm regForm) {
if (userRepository.existsUserByUsername(regForm.getUsername()))
return ResponseEntity.badRequest().body("This username is already taken! Choose another one!");
User user = new User(regForm.getUsername(),
encoder.encode(regForm.getPassword()),
UploadFileUtil.getStoragePath(regForm.getFile().getOriginalFilename()));
Set<Role> defaultRoles = new HashSet<>();
defaultRoles.add(roleRepository.findRoleByUserRole(Roles.USER));
user.setUserRoles(defaultRoles);
userRepository.save(user);
return ResponseEntity.ok().body("User registered successfully!");
}
}
感谢任何帮助。
答案 0 :(得分:0)
原因不在安全配置中,而是在UserPrincipal类中实现UserDetails。当您实现包括getter在内的所有方法时,默认情况下它们将返回false和null。因此,当我尝试从委托人那里获取字段时,它们将null返回给Authentication,因此密码不相同,并且我得到了未经授权的响应401。
因此,不要忘记以正确的方式覆盖方法,并且不会浪费时间来处理奇怪的错误。
感谢所有提供帮助的人,
public class UserPrincipal implements UserDetails {
private long id;
private String username;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public static UserPrincipal build(User user) {
List<GrantedAuthority> authorities = user.getUserRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getUserRole().name())
).collect(Collectors.toList());
return new UserPrincipal(
user.getId(),
user.getUsername(),
user.getPassword(),
authorities
); }
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}