如何基于Security框架兼容多套用户密码加密方式

一、说明
当已上线的系统存在使用其他的加密方式加密的密码数据,并且密码 不可逆 时,而新的数据采用了其他的加密方式,则需要同时兼容多种加密方式的密码校验。
例如下列几种情况:
- 旧系统用户的密码采用了 MD5 的加密方式,而升级框架后的新系统则采用 BCrypt 的加密方式;
- 当割接历史数据后会存在用户表中密码的 加密方式不统一 的问题,历史数据为 MD5 新数据为 BCrypt;
- 所以需要系统支持同时兼容多种加密方式的密码校验。
本文分享基于Security的PasswordEncoder来实现兼容多套用户密码加密方式。
二、DelegatingPasswordEncoder
在 spring Security 5.0之后,默认的密码加密方案其实是 DelegatingPasswordEncoder 它是一个代理类,而并非一种全新的密码加密方案,可以用来代理多种不同的密码加密方案。
代码参考:
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("bcrypt", new BCryptPasswordEncoder());
encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
encoders.put("SM3", new SM3PasswordEncoder());
Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder");
DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(encodingId, encoders);
delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(encoders.get(encodingId));
return delegatingPasswordEncoder;
自动会根据数据的
encodingId来使用对应的编译器处理密码
三、如何使用
3.1. 修改历史密码数据
修改旧的密码数据的值,添加前缀标识 encodingId 格式如下:
- 无盐值
{encodingId}密码
例如源密码为:$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
则修改为:
{bcrypt}$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
- 有盐值
{encodingId}{salt}密码
例如源密码为:
0758f7131c6c95c8e3df05e1ac50214c
则修改为:
{MD5}{5Hstj}0758f7131c6c95c8e3df05e1ac50214c
encodingId 的值可参考
PwdEncoderUtil类
如下图所示:

3条记录中,前两条为原有的历史记录使用的是
MD5的加密算法,然后新插入的数据使用的为bcrypt的加密算法,分别使用不同的前缀标识encodingId
3.2. 配置 PasswordEncoder 对象
使用 DelegatingPasswordEncoder 类来定义 PasswordEncoder 并且指定默认加密方式为 bcrypt
@Bean
public PasswordEncoder passwordEncoder() {
return PwdEncoderUtil.getDelegatingPasswordEncoder("bcrypt");
}
以下两种情况下都是使用默认的加密方式:
- 使用 encode 方法加密数据。
- 使用 matches 方法对比密文和原文时,密文没有 encodingId 标识。
3.3. 参考代码
扫码关注有惊喜!

如何基于Security框架兼容多套用户密码加密方式的更多相关文章
- Cognos权限认证CJP方式之用户密码加密
在项目开发过程中,用户往往对系统的安全都有明确的要求,下面针对cognos门户认证用户密码如何加密来提供一个简单的wf 1Cognos权限认证方式:CJP 2Cognos用户数据库类型:Oracle ...
- c# 对用户密码加密解密
一.使用16位.32位.64位MD5方法对用户名加密 1)16位的MD5加密 ? 1 2 3 4 5 6 7 8 9 10 11 12 /// <summary> /// 16位MD5加密 ...
- C#:使用MD5对用户密码加密与解密
C#中常涉及到对用户密码的加密于解密的算法,其中使用MD5加密是最常见的的实现方式.本文总结了通用的算法并结合了自己的一点小经验,分享给大家. 一.使用16位.32位.64位MD5方法对用户名加密 1 ...
- 转 C#:使用MD5对用户密码加密与解密
C#中常涉及到对用户密码的加密于解密的算法,其中使用MD5加密是最常见的的实现方式.本文总结了通用的算法并结合了自己的一点小经验,分享给大家. 一.使用16位.32位.64位MD5方法对用户名加密 1 ...
- Maven-009-Nexus 用户密码加密(安全必须)
信息数据大爆发的时代,我们关心什么?没错,数据安全!数据安全!数据安全!(重要事情说三遍,哈哈哈...) 之前我们存放在 maven settings.xml 文件中的 Nexus 私服用户密码都是明 ...
- Spring Security 5.x兼容多种密码加密方式
1 spring security PasswordEncoder spring security 5不需要配置密码的加密方式,而是用户密码加前缀的方式表明加密方式,如: {MD5}88e2d8cd1 ...
- java工具类学习,系统中用户密码加密总结
现在项目,用户注册登录部分很少有涉及到了,原因:现在热门开发框架都已经在底层帮我们做了一套用户注册,密码加密,登录认证,权限控制,缓存数据等基本功能. 这有利于项目的快速完成,只需要搬砖码畜们专注于业 ...
- MD5用户密码加密工具类 MD5Util
一般记录用户密码,我们都是通过MD5加密配置的形式.这里记录一下,MD5加密的工具类. package com.mms.utils; import java.security.MessageDiges ...
- Openfire用户密码加密解密
需求要求审核过程中都用匿名进行用户注册登录,注册用户审核通过后才使用openfire内置表 如何做到用户密码统一 Openfire是通过org.jivesoftware.util.Blowfish.j ...
- 使用bcrypt进行用户密码加密的简单实现
Bcrypt百度百科: bcrypt,是一个跨平台的文件加密工具.由它加密的文件可在所有支持的操作系统和处理器上进行转移.它的口令必须是8至56个字符,并将在内部被转化为448位的密钥. 除了对您的数 ...
随机推荐
- Knowledge Fusion例子
#! NX/KF 5.0 # #************************************************************************************ ...
- 第三阶段Blog
题目集7~9的总结性Blog 1.前言 一个月又过去了,又到了写blog的时候,相较于前两次Blog,这一次所要分析的内容从原先的侧重于类设计到了这次的侧重于结构设计.在完成作业的时候,尽管题目内提供 ...
- HTTP和HTTPS的定义和区别
http是什么? 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上.它指定了客户端可能发送给服务器什么样的消息以及 ...
- Mac下如何使用EVE-NG的telnet客户端和wireshark抓包
当我没有安装SecureCRT,点击启动的设备,弹出使用终端打开,但是由于eve中telnet使用的url是telnet xx.xx.xx.xx:xxxx 的形式,其在终端app中不能正常工作,tel ...
- PHP Redis - zSet(有序集合)
有序集合与集合一样,string类型元素的集合,不允许重复的成员. 有序集合,每个元素都会关联一个 double 类型的分数.Redis 通过分数为集合的成员进行从小到大的排序 有序集合的成员是唯一的 ...
- Debug --> CICFlowMeter的java版本安装及使用
一. 首先,给出一个很详细的配置链接!使用IDEA进行配置~ https://blog.csdn.net/BananaMan45/article/details/105473151?utm_mediu ...
- C 语言 scanf 格式化输入函数
C 语言 scanf 格式化输入函数 函数概要 scanf 函数从标准输入流中读取格式化字符串.与 printf 格式化输出函数相反,scanf 函数是格式化输入函数. 函数原型 #include & ...
- 实验1 Python开发环境使用和编程初体验
# print输出的几种用法 # 用法1:用于输出单个字符串或单个变量 print('hey, u') # 用法2: 用于输出多个数据项,用逗号分隔 print('hey', ' u') x,y,z ...
- 2月26日Android开发学习
1.App运行日志 Android采用Log工具打印日志,他讲各类日志划分为五个等级 (1)Log.e:表示错误信息,比如可能导致程序崩溃的异常. (2)Log.w:表示警告信息. (3)Log.i: ...
- 需要改动node_modules,并且别人也可以同步,插件 patch-package
patch-package 转自:https://www.cnblogs.com/lovewhatIlove/p/15724812.html 1.简介:有个功能需要修改node_modules里面的代 ...