为什么要用盐值加密?
我的理解:把密码或重要的数据存储在数据库中,如果数据库被攻击,密码容易泄露,会造成不安全的隐患。然而为什么要用“盐”呢?就是因为将密码进行加密的时候,如果有相同的密码,那么加密后的字符串也是一样的,这样也不是很安全。这里的“盐”就是唯一的数、随机数,一般来时把用户名当成“盐”,就能保证加密后字符串的唯一性。
盐值加密的操作步骤:
存密码步骤:
- 当用户对密码进行操作时,前端把密码FirstPassword1传递到后台
- 后端获取到FirstPassword1后,要么生成随机数、要么把用户名当成salt进行加密生成SecondPassword1
- 将SecondPassword1和salt保存在数据库中
取密码步骤:
- 用户输入密码后,把FirstPassword2传递到后台
- 后台拿到FirstPassword2后,从数据库中获取到salt,生成SecondPassword2
- 最后比对SecondPassword1和SecondPassword2密码是否一样。
实例代码
1、applicationContext.xml文件
<!--
3. 配置Realm,这里是用自己写的Realm -->
<bean id="jdbcRealm" class="com.ranqing.shirohello.ShiroRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="jdbcRealm" ref="jdbcRealm"/>
采用的是MD5码加密
2、写一个ShiroRealm.java,继承自AuthenticatingRealm
doGetAuthenticationInfo(AuthenticationToken token)方法中的代码:
//1、把AuthenticationToken转换为UsernamePasswordToken
UsernamePasswordToken upToken=(UsernamePasswordToken)token;
//2、从UsernamePasswordToken中来获取username
String username=upToken.getUsername();
//3、调用数据库的方法,从数据库中查询username对应的用户记录
System.out.println("从数据库中获取username:"+username+"所对应的用户信息.");
//4、若用户不存在,则可以抛出UnknownAccountException异常
if("unknown".equals(username)) {
throw new UnknownAccountException("用户不存在");
}
//5、根据用户信息的情况,决定是否需要抛出其他的AuthenticationException异常
if("monster".equals(username)) {
throw new LockedAccountException("用户被锁定");
}
//6、根据用户的情况,来构建AuthenticationInfo对象并返回,通常使用的实现类是:SimpleAuthenticationInfo
//以下信息是从数据库中获取的
//1). principal:认证的实体信息,可以是username,也可以是数据表对应的用户的实体类对象
Object principal=username;
//2). credentials:密码
Object credentials=null;//fc1709d0a95a6be30bc5926fdb7f22f4
if("admin".equals(username)) {
credentials="038bdaf98f2037b31f1e75b5b4c9b26e";
}else if("user".equals(username)) {
credentials="098d2c478e9c11555ce2823231e02ec1";
}
//3). realmName: 当前realm对象的name,调用父类的getName()方法即可
String realmName=getName();
//4)盐值
ByteSource credentialsSalt=ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info=null;
info=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return info;
生成MD5码的代码:
String hashAlgorithmName="MD5";
Object credentials="123456";
Object salt=ByteSource.Util.bytes("user");
int hashIterations=1024;
Object result=new org.apache.shiro.crypto.hash.SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
System.out.println(result);