我目前正在我的大学里做一个Spring Boot/ Angular项目。我正在努力使用BCryptPasswordEncoder的matches函数,它总是返回false。
User.java
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private Long id;
@NotNull
@Column(unique = true)
private String userName;
@NotNull
private String password;
@ElementCollection(fetch = FetchType.EAGER)
List<Role> roles;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
UserService.java
@Autowired
PasswordEncoder passwordEncoder;
public User register(UserDto userDto) throws EntityExistsException {
User existingUser = userRepository.findUserByUserName(userDto.userName);
if (existingUser != null)
throw new EntityExistsException();
User newUser = new User();
newUser.setUserName(userDto.userName);
newUser.setPassword(passwordEncoder.encode(userDto.password));
List<Role> roles = new ArrayList<Role>();
roles.add(Role.ROLE_USER);
newUser.setRoles(roles);
try {
newUser = userRepository.save(newUser);
} catch (Exception e) {
return null;
}
return newUser;
}
public boolean credentialsAreCorrect(String username, String password){
User user = userRepository.findUserByUserName(username);
if ( user == null)
return false;
return passwordEncoder.matches(password, user.getPassword());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
在Angular中,我使用以下函数进行注册:
register() {
const userName = 'testUser';
const password = 'testPassword';
this.httpClient.post('http://localhost:8080/user/register', {userName, password})
.subscribe(value => console.log(value));
}
成功注册后,我将对UserService.credentialsAreCorrect()
方法使用相同的凭据。但它总是返回false。credentialsAreCorrect()
方法的参数正确,并且找到了用户。
编辑
在调试服务器时,我注意到credentialsAreCorrect(username, password)
方法的password
参数的值始终为"PROTECTED"
。我认为这仅仅是为了调试,但它的值实际上是"PROTECTED"
。
在下面的拦截器中,我从请求头中获取密码:
@Component
public class AuthChannelInterceptor implements ChannelInterceptor {
private static final String USERNAME_HEADER = "login";
private static final String PASSWORD_HEADER = "passcode";
@Autowired
private WebSocketAuthenticatorService webSocketAuthenticatorService;
@Override
public Message<?> preSend(final Message<?> message, final MessageChannel channel) throws AuthenticationException {
final StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT == accessor.getCommand()) {
final String username = accessor.getFirstNativeHeader(USERNAME_HEADER);
final String password = accessor.getFirstNativeHeader(PASSWORD_HEADER);
final UsernamePasswordAuthenticationToken user = webSocketAuthenticatorService.getAuthenticatedOrFail(username, password);
accessor.setUser(user);
}
return message;
}
}
发布于 2019-12-12 01:15:59
我最终通过将password头更改为usercode
解决了这个问题。我仍然不明白,为什么这个值是"PROTECTED"
的,但至少它是有效的。
新的拦截器
@Component
public class AuthChannelInterceptor implements ChannelInterceptor {
private static final String USERNAME_HEADER = "login";
private static final String PASSWORD_HEADER = "usercode";
@Autowired
private WebSocketAuthenticatorService webSocketAuthenticatorService;
@Override
public Message<?> preSend(final Message<?> message, final MessageChannel channel) throws AuthenticationException {
final StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT == accessor.getCommand()) {
final String username = accessor.getFirstNativeHeader(USERNAME_HEADER);
final String password = accessor.getFirstNativeHeader(PASSWORD_HEADER);
final UsernamePasswordAuthenticationToken user = webSocketAuthenticatorService.getAuthenticatedOrFail(username, password);
accessor.setUser(user);
}
return message;
}
}
发布于 2020-06-20 05:03:45
我不确定这个问题是否已经解决了,但这里是我的五点意见:不使用最终字符串password = accessor.getFirstNativeHeader(PASSWORD_HEADER);,而必须使用最终字符串password = accessor.getPasscode();因为StompHeaderAccessor.StompPasscode不能直接访问,即toString()产生'PROTECTED‘。正如您已经提到的,accessor.getFirstNativeHeader("XXXX")适用于其他字段。(据我所知,客户端将STOMP_PASSCODE_HEADER设置为"PROTECTED“,这就是为什么会发生这种情况)
https://stackoverflow.com/questions/59256940
复制相似问题