需要解释 Java 应用程序中的 UsernamePasswordAuthenticationToken 用于身份验证的用法

bad*_*rir 0 spring-security jwt spring-boot

有人可以解释一下在 Java 应用程序中使用 UsernamePasswordAuthenticationToken 的以下代码吗?

UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
    userDetails, null,
    userDetails == null ?
        List.of() : userDetails.getAuthorities()
);
Run Code Online (Sandbox Code Playgroud)

我试图了解此代码中如何使用 UsernamePasswordAuthenticationToken 来处理身份验证,特别是关于 userDetails 参数和作为凭据传递的空值。我也对使用 List.of() 和 userDetails.getAuthorities() 来设置权限感到好奇。任何见解都会有帮助。谢谢你!

小智 6

身份UsernamePasswordAuthenticationToken验证实现有两个构造函数选项:

public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {

/**
     * This constructor can be safely used by any code that wishes to create a
     * UsernamePasswordAuthenticationToken, as the isAuthenticated()
     * will return false.
     *
     */
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
        super(null); // null is being passed to the authorities parameter
        this.principal = principal;
        this.credentials = credentials;
        setAuthenticated(false);
    }

    /**
     * This constructor should only be used by AuthenticationManager or
     * AuthenticationProvider implementations that are satisfied with
     * producing a trusted (i.e. isAuthenticated() = true) authentication token.
     * 
     */
    public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
            Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true); // must use super, as we override
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

第一个用于携带从请求中获取的身份验证数据,由能够AuthenticationProvider执行用户名密码样式身份验证的身份验证,无论用户的用户名是什么,无论他们是实际的用户名还是真实的用户名。电子邮件、电话号码、id 等。您可以在UserDetailsService实现中定义它。

第二个获取三个参数,将用户身份验证设置到 Spring Security 的安全上下文持有者中。基本上,通过将授予的权限列表添加到构造函数,您可以说用户已成功通过身份验证,即使该列表为空。

话虽如此,无需再将用户凭据存储在任何地方。事实上,保留存储的用户凭据将构成安全漏洞,因为您的Authentication对象按原样携带用户密码,即未进行哈希处理。

该类UsernamePasswordAuthenticationToken实际上有两个工厂方法,它们可以而且实际上应该用于显式构建经过身份验证或未经身份验证的令牌,即authenticated()unauthenticated()


public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {

    // Omitted constructors and fields for brevity

    /**
     * This factory method can be safely used by any code that wishes to create a
     * unauthenticated UsernamePasswordAuthenticationToken.
     *
     */
    public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, Object credentials) {
        return new UsernamePasswordAuthenticationToken(principal, credentials);
    }

    /**
     * This factory method can be safely used by any code that wishes to create a
     * authenticated UsernamePasswordAuthenticationToken.
     *
     */
    public static UsernamePasswordAuthenticationToken authenticated(Object principal, Object credentials,
            Collection<? extends GrantedAuthority> authorities) {
        return new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
    }
}

Run Code Online (Sandbox Code Playgroud)

如果开发人员利用 Spring Security 的AuthenticationManager----ProviderManagerAuthenticationProvider--- 对于用户名密码样式的身份验证来说DaoAuthenticationProvider---,他们可以放心,用户的凭据无论如何都会在身份验证之前被删除被设置到SecurityContextHolder. 该类从功能接口ProviderManager调用该方法,以从经过身份验证的令牌中删除凭据。eraseCredentials()CredentialsContainer

我强烈建议您使用 Spring Security 团队已经实现的内容,因为他们的实现已经过测试并被证明是安全的。

如果您想了解有关 Spring Security 身份验证架构的更多信息,可以查看Spring Security 参考文档的此页面。