【分享】如何让自己的系统用户登录密码加盐?

现在还有很多系统里在用Md5加密用户密码!

大约十年前,我开发的系统,密码都是使用MD5加密。

表单input密码框 输入后 使用user.password传到后端

后端拿到user.password后再次执行:

user.serPassword(HashKit.md5(user.getPassword()));

这样就把密码明文,使用MD5加密了!


安全性?

别开玩笑了,很容易破解的,虽然Md5不可逆!

但是我们有暴力!

中国数学家黄小云已经成功破解Md5!!


如何提升一下密码的安全性呢?

使用加盐Hash256即可:官方最佳实践代码

String salt = HashKit.generateSaltForSha256();
password = HashKit.sha256(salt + password);

因为老系统平台安全性升级,原始明文密码并不知晓 ,数据库里只存的MD5值。

所以,升级老系统加盐 只能新的密码也是拿到明文后Md5然后与盐值合并一起Hash256了!


下面给出的是老系统升级的方案代码,同样也适用于新系统,只不过不需要中间明文密码先Md5加密的过程了。


一、用户新增和注册时处理流程

image.png

String password = user.getPassword();
String pwdSalt = HashKit.generateSaltForSha256();
user.setPwdSalt(pwdSalt);
user.setPassword(HashKit.sha256(pwdSalt + HashKit.md5(pwd)));


二、用户登录处理流程

image.png

/**
* 通过用户名密码获取用户信息
* @param userName
* @param password
* @return
*/
public User getUser(String userName, String password) {
    if(notOk(userName) || notOk(password)){
        return null;
    }
    //通过用户名去找用户
    User user = findFirst(Kv.by("username", userName));
    if(user == null || notOk(user.getPwdSalt())) {return null;}
    String userPassword = user.getPassword();
    String hashPassword = HashKit.sha256(user.getPwdSalt() + HashKit.md5(password.trim()));
    if(hashPassword.equals(userPassword) == false) { return null; }
    return user;
}


这样就稍微增强了一下密码破解难度了,而且盐值随机的。

如果再难一点,可以每次登录成功后,刷新生成新的pwdSalt,每次都不一样。


扫码关注JFinal学院

【jfinalxueyuan】

image.png


精彩推荐:

【分享】用HuTool快速将JFinal的model数据导出Excel里

【分享】使用地图API实现IP转地理位置记录到登录日志中

【分享】如何实现异步导出Excel?

JFinal项目开发效率提升工具-JBolt插件使用简介

【解决】基于JFinal-Undertow的项目,如何快速导出War包?

【分享】使用JFinal4.8中的Slf4J日志门面配置,具体实现用Log4j2

【分享】微信公众平台开发常用两个内网穿透工具介绍,帮助本地开发环境方便调试

【技术】JFinal中使用Druid的监控

【视频】基于JFinal-undertow的项目打包与部署(linux centos7)


评论区

ihss23

2020-06-05 11:02

用户输入密码后,JS到后台拿随机六位数,返回的同时放到SESSION里。然后JS在页面SUBMIT前,六位数的按一定的逻辑插入到原密码中,然后MD5加密,再传到后台。后台再反过来解一次,并处理判断登录 。

山东小木

2020-06-05 11:08

@ihss23 是滴 很多不允许提交明文密码的 需要加密后传输 后端再处理

ihss23

2020-06-05 11:10

上面是我的做法。六位数的插入位置也是由这六个数决定的。

山东小木

2020-06-05 12:40

@ihss23 只要后端存储不是明文 通过可逆算法和一定规则 尽量不直接使用password 通过另一个动态字段辅助计算最后对比结果就行

JFinal

2020-06-05 15:03

@山东小木 密码 hash 只需要下面的方法就足够了:
String salt = HashKit.generateSaltForSha256();
password = HashKit.sha256(salt + password);

上面的用法是非常专业的方式,并不需要二次 hash。


最核心是下面几点:
1:一定要使用随机盐,用于防止彩虹表攻击

2:使用 sha256 而不是 md5,用于防止 hash 碰撞攻击。md5 已被中国数学家王小云破解,不再安全

3:sha512 更安全但hash值太长,sha256 足够安全 hash 值不是太长。所以 sha256 是最优方案。如果你的系统不是银行类的,采用 sha256 足够了,否则可以采用 sha512。

4:不要使用自己创造的 hash 算法,除非你是极度专业的该领域的专业人士,否则反而容易被破解。

5:不必使用二次 hash,二次 hash 并不能带来安全性的提升


jfinal club 采用的密码 hash、存储方案建立在作者大量、细致的调研,是十分专业的方案。

ihss23

2020-06-05 15:09

学习了。

山东小木

2020-06-05 18:53

@JFinal 恩 没有二次hash 最终就是盐值+明文密码先Md5 之所以使用Md5是因为平台里的老项目 已经使用了Md5加密的密码 并不知道明文 所以新改造后的加密算法 就索性明文的Md5值去与盐值合并后Has256了

山东小木

2020-06-05 19:00

@JFinal 我把分享内容稍微修改了一下,新系统按照JFInal CLub最佳实践代码即可,如果是老系统已经使用了Md5的 并且大量用户正在使用的系统,进行安全性升级的话 密码需要先MD5这一步了 保持与老密码一致

SuperEric

2020-06-05 23:28

@JFinal @山东小木 长知道了,一直没仔细去实践过几种算法结果的差别,波总的sha256讲解打开了一扇窗。

happyboy

2020-06-08 08:50