java - Spring Boot 不使用 CustomAuthenticationProvider 返回用户名

标签 java spring-boot spring-security

我一直在关注Baeldung的Spring 2FA tutorial实现 2FA。我已按照说明创建了 CustomAuthenticationProvider,但它的行为不符合预期。

奇怪的是,登录后,使用Principal.getName()时会显示我不熟悉的用户名格式:

com.appname.models.User@69080b62

由于应用程序的部分依赖于此来获取详细信息,这是不合适的,但我很难理解我哪里出了问题。我做了一些研究,但没有正确的术语和格式名称,我很难找到合适的结果。

    public Authentication authenticate(Authentication auth) throws AuthenticationException {

        User user = userRepository.findByUsername(auth.getName());

        if(user == null) {

            throw new BadCredentialsException("Invalid username or password");

        }

        if(user.getTwoFactor()) {

            //as per tutorial

        }
        //this returns the "correct" username
        System.out.println(user.getUsername());

        final Authentication result = super.authenticate(auth);
        //I suspect it's here that the issue is occurring, though any pointers in the right direction would be appreciated
        return new UsernamePasswordAuthenticationToken(user, result.getCredentials(), result.getAuthorities());

}

我期待的是实际的用户名,而不是...但是它目前正在返回 - 即用户的电子邮件地址。

最佳答案

我通过将最后几行更改为“解决”了该问题:

final Authentication result = super.authenticate(auth);

UserDetails userDetails = userDetailsService.loadUserByUsername(auth.getName());

return new UsernamePasswordAuthenticationToken(userDetails, 
        result.getCredentials(), userDetails.getAuthorities());

...其中 userDetailsS​​ervice 指向 Spring Security UserDetailsS​​ervice 的简单实现,它返回一个 Spring Security UserDetails 对象,如下所示:

@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) {

    User user = userRepository.findByUsername(username);

    if(user == null) throw new UsernameNotFoundException(username);

    Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
    for (Role role : user.getRoles()) {

        grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));

    }

    return new org.springframework.security.core.userdetails.User(user.getUsername(), 
            user.getPassword(), user.getEnabled(), user.getNonExpired(), 
            user.getCredentialsNonExpired(), user.getNonLocked(), grantedAuthorities);

}

这在我的应用程序的其他地方有效,所以我认为它也可以在这里工作。我相信我可以将最后一个参数保留为 result.getAuthorities()。我想我也可以重构,这样我就不会两次访问数据库,但现在我很高兴它能工作。

我不是 100% 确定为什么我相对简单的 User 模型不会返回用户名作为主体名称,可能还需要对我的 User 对象执行更多工作,以将用户名字符串显式标记为主要名称。

如果有人对任何进一步的更新感兴趣,或者可以为在此问题上遇到不确定性的其他人提供更多信息,请发表评论或提供另一个(可能更好)答案。

关于java - Spring Boot 不使用 CustomAuthenticationProvider 返回用户名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56304926/

相关文章:

java - 如何设置 `org.w3c.dom.element` 的第一个 child ?

java - 图像转换器java

java - 没有可用的 'xxx.xxx.xxx.xxx.MyUserDetailsService' 类型的合格 bean : expected at least 1 bean which qualifies as autowire candidate

spring - 寻找正确的方法 : Spring Social + Spring RESTful API + Spring WebApp + Mobile Clients

java - 如果用户未登录,则将其重定向到登录页面

java - 使 JInternal Frame 不可移动

java - POI 是否提供事件驱动的 API 来读取 XLS 和 XLSX 文件?

java - 在 Docker 中解密 Spring 属性值

postgresql - docker springboot 仅通过 docker-compose 连接到 postgres 5432

java - MVC 拦截器 vs Spring 安全过滤器 vs 其他东西......?