Shiro安全框架学习03 - 编码/加密
Posted 麦田
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro安全框架学习03 - 编码/加密相关的知识,希望对你有一定的参考价值。
md5加密
在涉及密码存储问题上,应该进行加密存储,而不能是明文,否则账号密码泄露,就会产生意想不到的后果。所以,通常都会采用非对称加密,什么是非对称呢,就是不可逆的,而md5就是这样一个算法。
如123456用md5加密后,得到字符串:e10adc3949ba59abbe56e057f20f883e
String password = "123456";
String encodedPassword = new Md5Hash(password).toString();
System.out.println(encodedPassword);
盐
上面讲了md5加密,但md5加密也有一些缺陷:如果我的密码是123456,你的也是123456,那么md5的值是一样的,通过比较加密后的字符串,就可以反推过来。
虽然md5不可逆,但可以用穷举法,把一些常用的密码的md5值记录下来,比如123,abcde等等,这样也可以破解一部分。
为了解决这个问题,引入了盐(salt)的概念,虽然每次123456的md5值都是e10adc3949ba59abbe56e057f20f883e
,但是加上盐之后,即123456+随机数,那么md5值就不一样了,这个随机数 就是盐,而这个随机数也会在数据库里保存下来,每个不同的用户,随机数也是不一样的。再者就是加密次数,可以加密一次 也可以加密多次,加密次数越多,密文的安全性也就越高。
String password = "123456";
String salt = new SecureRandomNumberGenerator().nextBytes().toString(); //随机数:盐
int times = 2; //加密次数
String algorithmName = "md5"; //散列算法
String encodedPassword = new SimpleHash(algorithmName,password,salt,times).toString();
System.out.println("密文:" + encodedPassword);
获取密文和盐
public class PasswordHelper
public static void main(String[] args)
String algorithmName = "md5";
String username = "itmyhome";
String password = "123456";
String salt1 = password;
String salt2 = new SecureRandomNumberGenerator().nextBytes().toHex();
int hashIterations = 2;
SimpleHash hash = new SimpleHash(algorithmName, password,
salt1 + salt2, hashIterations);
String encodedPassword = hash.toHex();
//每次输出结果都不一样
System.out.println("密文:" + encodedPassword); //b4b88b2ef28089f9c802df11bd216a33
System.out.println("盐:" + salt2); //713183f112f48824613f0f05d0d10060
修改Realm
public class UserRealm extends AuthorizingRealm
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
// TODO Auto-generated method stub
return null;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException
// TODO Auto-generated method stub
//获取账号密码
UsernamePasswordToken t = (UsernamePasswordToken) token;
String password = new String(t.getPassword());
String username = (String) token.getPrincipal();
//获取数据库种的密码、盐(此处写死,测试用)
User user = new User();
user.setUsername(username);
user.setPassword("b4b88b2ef28089f9c802df11bd216a33");
user.setSalt("713183f112f48824613f0f05d0d10060");
if (!"itmyhome".equals(username))
// 抛出 帐号找不到异常
throw new UnknownAccountException();
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), // 用户名
user.getPassword(), // 密码
ByteSource.Util.bytes(password + user.getSalt()),// salt=password+salt
getName() // realm name
);
return authenticationInfo;
ini配置
[main]
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=2
credentialsMatcher.storedCredentialsHexEncoded=true
userRealm=com.itmyhome.UserRealm
securityManager.realms=$userRealm
#这行很重要
userRealm.credentialsMatcher=$credentialsMatcher
通过credentialsMatcher.hashAlgorithmName=md5指定散列算法为md5,需要和生成密码时的一样
credentialsMatcher.hashIterations=2,散列迭代次数
credentialsMatcher.storedCredentialsHexEncoded=true表示是否存储散列后的密码为16进制
此处最需要注意的就是HashedCredentialsMatcher的算法需要和生成密码时的算法一样。
另外HashedCredentialsMatcher会自动根据AuthenticationInfo的类型是否是SaltedAuthenticationInfo来获取credentialsSalt盐。
测试类
public class ShiroTest
private static Logger logger = LoggerFactory.getLogger(ShiroTest.class);
public static void main(String[] args)
//获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:auth.ini");
//得到SecurityManager实例 并绑定给SecurityUtils
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("itmyhome","123456");
try
//登录,即身份验证
subject.login(token);
catch(org.apache.shiro.authc.AuthenticationException e)
//身份验证失败
e.printStackTrace();
System.out.println(subject.getPrincipal());
System.out.println("User is authenticated: " + subject.isAuthenticated());
以上是关于Shiro安全框架学习03 - 编码/加密的主要内容,如果未能解决你的问题,请参考以下文章