Spring Boot PasswordEncoder.matches始终为false

时间:2019-12-09 21:30:40

标签: spring spring-boot

我目前正在大学里从事Spring Boot / Angular项目的工作。我正在努力与BCryptPasswordEncoder的matchs函数一起使用,该函数始终返回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()方法的参数正确,并且已找到用户。

编辑

调试服务器时,我注意到password方法的credentialsAreCorrect(username, 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;
    }
}

2 个答案:

答案 0 :(得分:0)

我终于通过将密码标题更改为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;
    }
}

答案 1 :(得分:0)

我不确定是否已解决该问题,但这是我的5美分:而不是使用最终的String password = accessor.getFirstNativeHeader(PASSWORD_HEADER);您必须使用最终的String密码= accessor.getPasscode();因为不能直接访问StompHeaderAccessor.StompPasscode,即toString()产生“ PROTECTED”。如前所述,accessor.getFirstNativeHeader(“ XXXX”)适用于其他字段。 (据我了解,客户端将STOMP_PASSCODE_HEADER设置为“ PROTECTED”,这就是这种情况的原因)