ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Shiro学习(六)——MD5加密与盐值

2021-09-25 23:04:03  阅读:187  来源: 互联网

标签:加密 盐值 HashedCredentialsMatcher realm MD5 帐号密码 Shiro md5


前言

上一篇文章讲了shiro如何配置加密服务。这篇文章我们用md5加密算法作为例子。md5算法是常见的加密算法,另外为了提高安全性,通常还会加上盐值。这些如何进行配置呢,在本文进行展示。

加盐值是怎么回事?

像MD5这类加密,对于同一个密码,加密之后的密码都是一样的。如果我们初始化系统,把所有用户设置密码为123456,那经过md5加密之后,所有密文也都是相同的。那盗用者只要破解这个密文,那所有密文相同的帐号也会被盗用。如何避免这种情况呢?加盐。加盐的操作,就是明文加密过程中,把盐(其实就是一小截字符串,例如abc)和明文拼接到一起加密。因为每个帐号的盐值不同,同样明文,加密出来的密文都不一样,这样帐号安全性就大大提高了。

配置用户帐号密码

一开始我是准备把用户名帐号弄在ini文件上的形式,但是折腾了好久都不行。查看了源码,因为一是IniRealm读取ini文件的帐号密码,就没有读取盐值的功能,二是使用的SimpleAccount类存储认证信息也不包含盐值属性。所以如果读者想使用ini文件进行帐号密码管理的话,必须重写这个类的一些方法才行。由于比较麻烦,我就放弃这条路线了。

我选择使用数据库配置帐号密码的形式,这样默认的JdbcRealm是支持包含盐值的密文存储方式。看系列第一篇文章《Shiro学习(一)——Shiro配置与快速开始》,如下图所示,默认users表的password_salt就是存储盐值用的。

 

 接着我们编写生成加密的密文和盐值的方法,这里我们传入123作为密码,以abcd作为盐值,以md5作为加密算法,进行10次加密迭代:

public void encryptMD5(String password) {
	System.out.println("加密后的盐值:"+Base64.encodeToString("abcd".getBytes()));
	SimpleHash hash = new SimpleHash("md5", password, "abcd", 10);	
	System.out.println("加密后的密码:"+hash.toString());
}

执行这段代码,输出结果:

由于JdbcRealm默认会对盐值作Base64解密,我们应该把加密后的盐值写入数据库中,如下图:

 这样准备工作就完成了

初始化配置并测试

下一步,我们通过数据库配置方式,测试认证是否生效。编写如下代码:

public static void main(String[] args) throws Exception {
	DefaultSecurityManager securityManager = new DefaultSecurityManager();
	JdbcRealm realm = new JdbcRealm();
	Class<DruidDataSource> clazz = DruidDataSource.class;
	DruidDataSource dataSource = clazz.newInstance();
	dataSource.setUsername("root");
	dataSource.setPassword("");
	dataSource.setUrl("jdbc:mysql://localhost:3306/shiro");
	dataSource.setDriverClassName("com.mysql.jdbc.Driver");
	realm.setDataSource(dataSource);
	realm.setPermissionsLookupEnabled(true);
	
	HashedCredentialsMatcher cm = new HashedCredentialsMatcher();
	cm.setHashAlgorithmName("md5");
	cm.setHashIterations(10);
	realm.setCredentialsMatcher(cm);
	realm.setSaltStyle(SaltStyle.COLUMN);
	
	securityManager.setRealm(realm);
	SecurityUtils.setSecurityManager(securityManager);
	Subject subject = SecurityUtils.getSubject();
	
	UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
	try {
		subject.login(token);
		System.out.println("ok");
	} catch (AuthenticationException e) {
		e.printStackTrace();
	}
	subject.logout();
}

 2-11行是配置数据库连接的代码,这个我们前面的文章也有讲,就不细述了。13-17行是匹配密码的关键。上一篇文章《Shiro学习(五)——密码的加密解密》我们讲过,密码匹配的关键点之一是CredentialsMatcher接口的实现类。因为这次使用md5加密,所以我们就用HashedCredentialsMatcher类来进行配陪。14行设置加密算法为md5,15行设置迭代次数为10次,这些配置与我们之前加密的方式要一致。16行把HashedCredentialsMatcher配置到jdbcRealm中,当需要匹配帐号密码时,jdbcRealm就会调用HashedCredentialsMatcher了。17行设置加盐方式为SaltStyle.COLUMN。默认情况是SaltStyle.NO_SALT不加盐。

执行代码,如果没其他异常的话,应该会输出ok字样。如果报下图的错误,那就是帐号密码不匹配。这种情况需要检查帐号密码是否配置正确,盐值是否有加密,是否设置了盐值加密方式SaltStyle.COLUMN。

 如果还是找不到,那就要断点到org.apache.shiro.authc.credential.HashedCredentialsMatcher的doCredentialsMatch方法里,看看传入的token(用户提交的信息)与info(数据库获取的信息)是否有问题,再寻找问题出在哪。

小结

这部分内容并不复杂,但是我在使用ini文件配置时卡了很久,另外在盐值也要经过base64加密的问题上也卡了很久。后来都需要通过跟踪源码调试才明白。网上找的文章,绝大多数都是抄来抄去,基本都是自定义一个realm,还把帐号密码盐值写在里面。如果直接搬来改造,还是挺麻烦的。这么简单的业务功能shiro已经提供,我们没必要什么都去扩展,去自定义。

标签:加密,盐值,HashedCredentialsMatcher,realm,MD5,帐号密码,Shiro,md5
来源: https://blog.csdn.net/sadoshi/article/details/120197827

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有