Java SecurityContextHolder.getContext().getAuthentication().getCredentials()在身份验证后返回null
我创建了一个简单的SpringWebMVC应用程序,但我有一个问题。在身份验证之后,我尝试获取一个身份验证对象,由于某种原因,它的凭据为空 在此项目中,我有一个自定义AuthenticationProvider,如下所示:Java SecurityContextHolder.getContext().getAuthentication().getCredentials()在身份验证后返回null,java,spring-mvc,spring-security,Java,Spring Mvc,Spring Security,我创建了一个简单的SpringWebMVC应用程序,但我有一个问题。在身份验证之后,我尝试获取一个身份验证对象,由于某种原因,它的凭据为空 在此项目中,我有一个自定义AuthenticationProvider,如下所示: @Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Autowired private UserService userServi
@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);
}
}
我感兴趣的是,这是在spring security中故意做的,还是我遗漏了什么。我通过将用户对象传递给UsernamePasswordAuthenticationToken构造函数,而不是将用户名传递给主体,解决了这个问题 我改变了这一点:
Authentication auth = new
UsernamePasswordAuthenticationToken(username, password, authorities);
为此:
Authentication auth = new
UsernamePasswordAuthenticationToken(user, password, authorities);
在控制器中,我让用户这样:
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
我通过将用户对象传递给UsernamePasswordAuthenticationToken构造函数而不是用户名来解决这个问题 我改变了这一点:
Authentication auth = new
UsernamePasswordAuthenticationToken(username, password, authorities);
为此:
Authentication auth = new
UsernamePasswordAuthenticationToken(user, password, authorities);
在控制器中,我让用户这样:
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
由于身份验证成功后将删除凭据,因此必须将橡皮擦凭据False添加到AuthenticationManagerBuilder配置中。就像下面的代码:
@Autowired
private CustomAuthenticationProvider customAuthProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthProvider).eraseCredentials(false);
}
这已经晚了,但我认为根据问题,这是正确的答案。因为认证成功后凭据将被删除,所以必须将橡皮擦凭据False添加到AuthenticationManagerBuilder配置中。就像下面的代码:
@Autowired
private CustomAuthenticationProvider customAuthProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthProvider).eraseCredentials(false);
}
虽然已经晚了,但我认为这是问题的正确答案。为什么要按用户名和密码搜索?您应该只按用户名搜索。然后在“身份验证”方法中比较密码?为什么按用户名和密码搜索?您应该只按用户名搜索。然后在authenticate方法中比较密码?我已经用这个配置尝试了好几次,它对我不起作用,getCredentials返回Null您可以详细说明customAuthProvider吗?那是什么东西?它应该实现/扩展什么?customAuthProvider是问题中提到的CustomAuthenticationProvider的对象。我已经更新了答案。我用这个配置尝试了好几次,它对我不起作用,getCredentials返回Null你能详细介绍一下customAuthProvider吗?那是什么东西?它应该实现/扩展什么?customAuthProvider是问题中提到的CustomAuthenticationProvider的对象。我已经更新了答案。