一.说明
1.分析
通过MD5+salt+hash散列进行用户登录查询。
重点:(1)加密存储到数据库(2)验证登录用户信息和数据库信息是否一致
2.目录结构
二.范例
1.调用类
(1)代码块
package com.fengmo;
import com.relam.CustomerMD5;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
/**
* 测试:使用MD5+salt+hash散列的业务逻辑和使用
*/
public class TestCustomerMD5 {
public static void main(String[] args) {
//1.创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.1创建realm
CustomerMD5 customerMD5 = new CustomerMD5();
//2.2创建hash凭证管理器
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//2.3设置加密的算法是MD5
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
//2.4设置散列次数
hashedCredentialsMatcher.setHashIterations(1024);
//2.4设置realm为hash凭证管理器【以上为管理器的配置】
customerMD5.setCredentialsMatcher(hashedCredentialsMatcher);
//2.5注入realm
securityManager.setRealm(customerMD5);
//3.将安全管理器注入到安全工具
SecurityUtils.setSecurityManager(securityManager);
//4.通过subject获取容器对象
Subject subject = SecurityUtils.getSubject();
//5.创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
//6.认证
try{
subject.login(token);
System.out.println("没有异常,则登录成功");
}catch (UnknownAccountException e){ //用户名不存在
e.printStackTrace();
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e2){ //密码错误
e2.printStackTrace();
System.out.println("密码错误");
}
}
}
(2)范例
2.md5加密类【用于注册用户时存储密码进行加密】
(1)代码块
package com.md5;
import org.apache.shiro.crypto.hash.Md5Hash;
/*
MD5算法:
1.作用:一般用于加密或者签名(校验和)
2.特点:MD5算法不可逆,如何内容相同无论执行多少次md5生成结果始终是一致
3.生成结果:始终是一个16进制32位长度字符串
4.加密时选择MD5+Salt(盐)
*/
public class MD5Demo {
public static void main(String[] args) {
//1.创建MD5算法
Md5Hash md5Hash = new Md5Hash();
//1.2使用byte【】数组形式的参数加密
md5Hash.setBytes("123".getBytes());
//1.3查看加密的结果
String hex = md5Hash.toHex(); //返回加密后的字符串
System.out.println("这是错误的密码算法"+hex);
//以上的错误加密写法
//正确写法一【不加salt(盐)的算法,不推荐】
//2.1.创建MD5算法
Md5Hash md5Hash2 = new Md5Hash("123"); //构造参数存储需要加密的明文字符串
//2.2获取加密后的结果
//存储数据库时就用md5Hash2.toHex()
System.out.println("这是正确的密码算法(不加salt)"+md5Hash2.toHex());
//正确写法二【加salt(盐)的算法,推荐】
//3.1使用md5+salt处理
Md5Hash md5Hash3 = new Md5Hash("123","X0*7ps"); //salt可以随意写
//3.2获取加密后的结果
//存储数据库时就用md5Hash2.toHex()
System.out.println("这是正确的密码算法(加salt)"+md5Hash3.toHex());
//正确写法三 MD5 + salt + hash散列
//4.1使用md5+salt+hash散列
Md5Hash md5Hash4 = new Md5Hash("123","X0*7ps",1024);
//4.2获取加密后的结果
//存储数据库时就用md5Hash2.toHex()
System.out.println("这是正确的密码算法(加salt加hash散列)"+md5Hash4.toHex());
}
}
(2)范例
3.认证类【用于登录用户验证用户信息】
(1)代码块
package com.relam;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
/**
* 自定义realm实现 + MD5 + salt + hash散列
* 将认证/获取数据的来源转为数据库的实现
*/
public class CustomerMD5 extends AuthorizingRealm {
//这是授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//这是认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息【获取用户名】
String principal = (String)token.getPrincipal();
//根据用户名查询数据库
if("xiaochen".equals(principal)){ //xiaochen以后是从数据库进行获取
//明文存储
//return new SimpleAuthenticationInfo(principal,"123",this.getName());
//md5算法存储
//return new SimpleAuthenticationInfo(principal,"202cb962ac59075b964b07152d234b70",this.getName());
//参数一是身份信息,参数二是数据库获取的密码【MD5+salt】,参数三是salt,参数四是realm的名称
//return new SimpleAuthenticationInfo(principal, "8a83592a02263bfe6752b2b5b03a4799", ByteSource.Util.bytes("X0*7ps"), this.getName());
//参数一是身份信息,参数二是数据库获取的密码【MD5+salt+散列】,参数三是salt,参数四是realm的名称
return new SimpleAuthenticationInfo(principal,"e4f9bf3e0c58f045e62c23c533fcf633", ByteSource.Util.bytes("X0*7ps"),this.getName());
}
return null;
}
}