我创建了一个简单的spring web mvc应用程序,但我遇到了一个问题。身份验证后,我尝试获取身份验证对象,由于某种原因,它的凭据为null。
在这个项目中,我有一个自定义的AuthenticationProvider,如下所示:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@PostConstruct
public void init() {
roleService.AddStandardRolesIfNeeded();
userService.AddUserWithAdminRoleIfNotExists("a");
}
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Object credentials = authentication.getCredentials();
if(!(credentials instanceof String)) {
return null;
}
String username = authentication.getName();
String password = credentials.toString(); //password isn't null here
User user = userService.findByUsernameAndPassword(username, password);
if(user == null) {
throw new BadCredentialsException("Authentication failed for " + username);
}
List<GrantedAuthority> authorities = new ArrayList<>();
for(Role role : user.getRoles()) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
Authentication auth = new
UsernamePasswordAuthenticationToken(username, password, authorities);
return auth;
}
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
我对是否有意在春季安全中完成它或我遗漏了一些东西感兴趣。
答案 0 :(得分:0)
我通过将用户对象传递给UsernamePasswordAuthenticationToken
构造函数而不是用户名代替主体来解决了这个问题。
我更改了此内容
Authentication auth = new
UsernamePasswordAuthenticationToken(username, password, authorities);
对此:
Authentication auth = new
UsernamePasswordAuthenticationToken(user, password, authorities);
在控制器中,我得到了用户,
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
答案 1 :(得分:0)
由于认证成功后凭据将被删除,因此必须将eraseCredentials(false)
添加到AuthenticationManagerBuilder
配置中。就像下面的代码:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthProvider).eraseCredentials(false);
}
这很晚了,但是我认为这是根据问题的正确答案。
答案 2 :(得分:-1)
应该使身份验证更像这样:
@Override
public Authentication authenticate(final Authentication authentication) {
//better to use optionals with repositories, they greatly reduce NullPointer exception quantity
final SomeUser user = UserRepository.findByUsernameIgnoreCase(authentication.getName())
.orElseThrow(() -> new UsernameNotFoundException("some message"));
try {
final Authentication auth = super.authenticate(authentication);
//can add logic here, such as login time recording
return auth;
} catch (...) {
//handle various exceptions here, for example failed login attempts and user locking
}