首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring Boot PasswordEncoder.matches always false

Spring Boot PasswordEncoder.matches always false
EN

Stack Overflow用户
提问于 2019-12-10 05:30:41
回答 2查看 1.1K关注 0票数 1

我目前正在我的大学里做一个Spring Boot/ Angular项目。我正在努力使用BCryptPasswordEncoder的matches函数,它总是返回false。

User.java

代码语言:javascript
运行
复制
@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

代码语言:javascript
运行
复制
@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中,我使用以下函数进行注册:

代码语言:javascript
运行
复制
  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"

在下面的拦截器中,我从请求头中获取密码:

代码语言:javascript
运行
复制
@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;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-12 01:15:59

我最终通过将password头更改为usercode解决了这个问题。我仍然不明白,为什么这个值是"PROTECTED"的,但至少它是有效的。

新的拦截器

代码语言:javascript
运行
复制
@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;
    }
}
票数 0
EN

Stack Overflow用户

发布于 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“,这就是为什么会发生这种情况)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59256940

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档