SpringSecurity中的密码加密

举报
周杰伦本人 发表于 2022/05/11 09:49:40 2022/05/11
【摘要】 SpringSecurity中的密码加密 密码加密 密码匹配 总结 SpringSecurity中的密码加密今天这篇文章给大家介绍一下Spring Security中的密码加密的相关源码: 密码加密SpringSecurity中默认的加密方案是DelegatingPasswordEncoder,它是一个代理类,主要用来代理不同的密码加密方案,它是由PasswordEncoderFactor...

SpringSecurity中的密码加密

今天这篇文章给大家介绍一下Spring Security中的密码加密的相关源码:

密码加密

SpringSecurity中默认的加密方案是DelegatingPasswordEncoder,它是一个代理类,主要用来代理不同的密码加密方案,它是由PasswordEncoderFactories的createDelegatingPasswordEncoder方法提供默认的DelegatingPasswordEncoder实例,可以看到默认加密方案是bcrypt

public class PasswordEncoderFactories {
    public static PasswordEncoder createDelegatingPasswordEncoder() {
        String encodingId = "bcrypt";
        Map<String, PasswordEncoder> encoders = new HashMap();
        encoders.put(encodingId, new BCryptPasswordEncoder());
        encoders.put("ldap", new LdapShaPasswordEncoder());
        encoders.put("MD4", new Md4PasswordEncoder());
        encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
        encoders.put("noop", NoOpPasswordEncoder.getInstance());
        encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
        encoders.put("scrypt", new SCryptPasswordEncoder());
        encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
        encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
        encoders.put("sha256", new StandardPasswordEncoder());
        encoders.put("argon2", new Argon2PasswordEncoder());
        return new DelegatingPasswordEncoder(encodingId, encoders);
    }

    private PasswordEncoderFactories() {
    }

从源码中我们可以看出来,它还支持其他的加密方式例如我们常用的MD5加密,值得注意的是,我们在前几篇文章中定义用户名密码的时候使用了noop加密,通过源码可以看出来,设置调用的是NoOpPasswordEncoder的实例,从类名我们也能猜出来,这是一种不经过加密的方式,也就是存放的直接是明文,这在我们测试的时候可以实现,一般情况下是不使用的,因为有一定的风险存在。

DelegatingPasswordEncoder实现了PasswordEncoder接口,

实现encode接口,加密完成后给加密后的字符串添加前缀,表示采用的哪种加密方案。

public String encode(CharSequence rawPassword) {
    return "{" + this.idForEncode + "}" + this.passwordEncoderForEncode.encode(rawPassword);
}

这就就是进行加密了

密码匹配

实现密码匹配接口:

public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
    if (rawPassword == null && prefixEncodedPassword == null) {
        return true;
    } else {
        String id = this.extractId(prefixEncodedPassword);
        PasswordEncoder delegate = (PasswordEncoder)this.idToPasswordEncoder.get(id);
        if (delegate == null) {
            return this.defaultPasswordEncoderForMatches.matches(rawPassword, prefixEncodedPassword);
        } else {
            String encodedPassword = this.extractEncodedPassword(prefixEncodedPassword);
            return delegate.matches(rawPassword, encodedPassword);
        }
    }
}
private String extractId(String prefixEncodedPassword) {
        if (prefixEncodedPassword == null) {
            return null;
        } else {
            int start = prefixEncodedPassword.indexOf("{");
            if (start != 0) {
                return null;
            } else {
                int end = prefixEncodedPassword.indexOf("}", start);
                return end < 0 ? null : prefixEncodedPassword.substring(start + 1, end);
            }
        }
    }

先调用extractId方法从加密字符串中提取具体的加密方案,就是{ }中的字符,拿到后从idToPasswordEncoder中匹配,为null采用默认的defaultPasswordEncoderForMatches的密码匹配器进行匹配。

开发者向spring容器中注册一个PasswordEncoder实例,AuthenticationManager使用该实例,没有提供就使用DelegatingPasswordEncoder的实例。

总结

好了 这就是Spring Security的密码加密相关的源码了,它的默认加密方式是BCryptPasswordEncoder,我们生产中一般使用MD5加密,Spring Security也是支持这种方式,只要我们在构造的时候传入MD5就可以

@Bean
public MessageDigestPasswordEncoder messageDigestPasswordEncoder(){
    
    return new MessageDigestPasswordEncoder("MD5");
}

这篇文章先到这里,对应密码加密和密码匹配的逻辑比较简单,下篇文章我们将讲解Spring Security的其他知识点,欢迎订阅我的博客。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。