UserDetails接口及子类实现

继承图

在这里插入图片描述
UserDetails(位于org.springframework.security.core.userdetails包下)主要和用户信息有关的接口,该接口是提供用户信息的核心接口。该接口实现仅仅存储用户的信息。后续会将该接口提供的用户信息封装到认证对象Authentication中去。UserDetails 默认提供了如下方法:

public interface UserDetails extends Serializable {
	
	// 权限
	// 用户的权限集, 默认需要添加ROLE_ 前缀
    Collection<? extends GrantedAuthority> getAuthorities();
	
	// 密码
	// 用户的加密后的密码, 不加密会使用{noop}前缀
    String getPassword();
	
	// 用户名
    String getUsername();
	
	// 帐户未过期
    boolean isAccountNonExpired();
 
    // 帐户未锁定
    boolean isAccountNonLocked();
	
	// 凭证是否过期
    boolean isCredentialsNonExpired();
	
	// 用户是否可用
    boolean isEnabled();
}

其子类主要有两个:

User(位于org.springframework.security.core.userdetails包下),又类名得知这个类是用户类,是存放待认证的用户信息。如从数据库查出的用户信息和从缓存中获取的用户信息都可以封装到此类中,最终交给SpringSecurity进行用户信息认证。其实现代码如下:

// CredentialsContainer 凭证容器
public class User implements UserDetails, CredentialsContainer {
	// 序列号id
    private static final long serialVersionUID = 550L;
	// 日志记录
    private static final Log logger = LogFactory.getLog(User.class);
	// 密码
    private String password;
	// 用户名
    private final String username;
	// 权限
    private final Set<GrantedAuthority> authorities;
	// 帐户未过期
    private final boolean accountNonExpired;
	// 帐户未锁定
    private final boolean accountNonLocked;
	// 凭证是否过期
    private final boolean credentialsNonExpired;
	// 用户是否可用
    private final boolean enabled;
	
	// 构造器 初始化 用户名 密码 权限
    public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }
	
	// 构造器 初始化 用户名 密码 是否启用 账户是否过期 账户是否锁定 凭证是否过期 权限
    public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        Assert.isTrue(username != null && !"".equals(username) && password != null, "Cannot pass null or empty values to constructor");
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
    }
	
	// 获取权限
    public Collection<GrantedAuthority> getAuthorities() {
        return this.authorities;
    }
	
	// 获取密码
    public String getPassword() {
        return this.password;
    }
	
	// 获取用户名
    public String getUsername() {
        return this.username;
    }
	
	// 获取是否启用状态
    public boolean isEnabled() {
        return this.enabled;
    }
	
	// 获取账户是否过期状态
    public boolean isAccountNonExpired() {
        return this.accountNonExpired;
    }
	
	// 获取账户是否锁定状态
    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }
	
	// 获取凭证是否过期状态
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }
	
	// 擦除凭证
    public void eraseCredentials() {
        this.password = null;
    }
	
	// 获取权限
    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet(new User.AuthorityComparator());
        Iterator var2 = authorities.iterator();

        while(var2.hasNext()) {
            GrantedAuthority grantedAuthority = (GrantedAuthority)var2.next();
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }

        return sortedAuthorities;
    }

    public boolean equals(Object obj) {
        return obj instanceof User ? this.username.equals(((User)obj).username) : false;
    }

    public int hashCode() {
        return this.username.hashCode();
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.getClass().getName()).append(" [");
        sb.append("Username=").append(this.username).append(", ");
        sb.append("Password=[PROTECTED], ");
        sb.append("Enabled=").append(this.enabled).append(", ");
        sb.append("AccountNonExpired=").append(this.accountNonExpired).append(", ");
        sb.append("credentialsNonExpired=").append(this.credentialsNonExpired).append(", ");
        sb.append("AccountNonLocked=").append(this.accountNonLocked).append(", ");
        sb.append("Granted Authorities=").append(this.authorities).append("]");
        return sb.toString();
    }

    public static User.UserBuilder withUsername(String username) {
        return builder().username(username);
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    /** @deprecated */
    @Deprecated
    public static User.UserBuilder withDefaultPasswordEncoder() {
        logger.warn("User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications.");
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        User.UserBuilder var10000 = builder();
        Objects.requireNonNull(encoder);
        return var10000.passwordEncoder(encoder::encode);
    }

    public static User.UserBuilder withUserDetails(UserDetails userDetails) {
        return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled());
    }
	
	// 通过建造者模式 构建User对象
    public static final class UserBuilder {
        private String username;
        private String password;
        private List<GrantedAuthority> authorities;
        private boolean accountExpired;
        private boolean accountLocked;
        private boolean credentialsExpired;
        private boolean disabled;
        private Function<String, String> passwordEncoder;

        private UserBuilder() {
            this.passwordEncoder = (password) -> {
                return password;
            };
        }

        public User.UserBuilder username(String username) {
            Assert.notNull(username, "username cannot be null");
            this.username = username;
            return this;
        }

        public User.UserBuilder password(String password) {
            Assert.notNull(password, "password cannot be null");
            this.password = password;
            return this;
        }

        public User.UserBuilder passwordEncoder(Function<String, String> encoder) {
            Assert.notNull(encoder, "encoder cannot be null");
            this.passwordEncoder = encoder;
            return this;
        }

        public User.UserBuilder roles(String... roles) {
            List<GrantedAuthority> authorities = new ArrayList(roles.length);
            String[] var3 = roles;
            int var4 = roles.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String role = var3[var5];
                Assert.isTrue(!role.startsWith("ROLE_"), () -> {
                    return role + " cannot start with ROLE_ (it is automatically added)";
                });
                authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
            }

            return this.authorities((Collection)authorities);
        }

        public User.UserBuilder authorities(GrantedAuthority... authorities) {
            return this.authorities((Collection)Arrays.asList(authorities));
        }

        public User.UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
            this.authorities = new ArrayList(authorities);
            return this;
        }

        public User.UserBuilder authorities(String... authorities) {
            return this.authorities((Collection)AuthorityUtils.createAuthorityList(authorities));
        }

        public User.UserBuilder accountExpired(boolean accountExpired) {
            this.accountExpired = accountExpired;
            return this;
        }

        public User.UserBuilder accountLocked(boolean accountLocked) {
            this.accountLocked = accountLocked;
            return this;
        }

        public User.UserBuilder credentialsExpired(boolean credentialsExpired) {
            this.credentialsExpired = credentialsExpired;
            return this;
        }

        public User.UserBuilder disabled(boolean disabled) {
            this.disabled = disabled;
            return this;
        }

        public UserDetails build() {
            String encodedPassword = (String)this.passwordEncoder.apply(this.password);
            return new User(this.username, encodedPassword, !this.disabled, !this.accountExpired, !this.credentialsExpired, !this.accountLocked, this.authorities);
        }
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
        private static final long serialVersionUID = 550L;

        private AuthorityComparator() {
        }

        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            if (g2.getAuthority() == null) {
                return -1;
            } else {
                return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority());
            }
        }
    }
}
  • MutableUserDetails(位于org.springframework.security.provisioning包下)可变用户详细信息,看着名称就知道这个接口肯定定义的用户详情信息时可以改变的,实现此接口的子类中的用户信息可能随时发生改变,并不是固定不变的;接口中只定义了一个方法setPassword方法,用于更新用户的密码。
interface MutableUserDetails extends UserDetails {
    void setPassword(String password);
}
  • MutableUser(位于org.springframework.security.provisioning包下)可变用户:
class MutableUser implements MutableUserDetails {
    private static final long serialVersionUID = 560L;
    // 密码
    private String password;
    // 用户详情信息
    private final UserDetails delegate;
 
    // 构造器 初始化用户信息
    MutableUser(UserDetails user) {
        this.delegate = user;
        this.password = user.getPassword();
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.delegate.getAuthorities();
    }

    public String getUsername() {
        return this.delegate.getUsername();
    }

    public boolean isAccountNonExpired() {
        return this.delegate.isAccountNonExpired();
    }

    public boolean isAccountNonLocked() {
        return this.delegate.isAccountNonLocked();
    }

    public boolean isCredentialsNonExpired() {
        return this.delegate.isCredentialsNonExpired();
    }

    public boolean isEnabled() {
        return this.delegate.isEnabled();
    }
}

在项目中也可以定义自己的用户实体类,只要实现UserDetails即可,交由SpringSecurity进行用户信息认证:

public class MyUser implements UserDetails {
    
    private String password;
    private String username;
    .....

    public MyUser(String password, String username,....) {
        this.password = password;
        this.username = username;
        .....
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值