Shiro加密
散列算法
散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如 MD5、SHA 等。一般进行散列时最好提供一个 噪声,这样可以使破解密码的难度变大。
以下是MD5加密算法的一个演示:
public class TestMD5 {
@Test
public void test1() {
String pwd = "123456";
Md5Hash hash = new Md5Hash(pwd);
System.out.println("使用md5加密后的结果:" + hash.toString());
//第一个参数为要加密的数据,第二个参数为噪声,第三个参数为加密的次数
Md5Hash mHash = new Md5Hash(pwd, "ffwws", 1);
System.out.println("使用md5添加噪声加密后的结果:" + mHash.toString());
mHash = new Md5Hash(pwd, "ffwws", 2);
System.out.println("使用md5添加噪声加密后的结果:" + mHash.toString());
}
}
Shiro提供的接口
PasswordService接口
此接口提供加密密码和验证密码的功能。
public interface PasswordService {
String encryptPassword(Object plaintextPassword) throws IllegalArgumentException;
boolean passwordsMatch(Object submittedPlaintext, String encrypted);
}
此接口有两个方法,第一个方法的作用是输入明文密码后得到加密的密码,参数是未加密的密码,第二个方法的作用是比较用户输入的明文密码和系统提供的密码(已加密)是否相同,第一个参数:用户输入的密码,第二个参数:系统提供的密码。
CredentialsMatcher接口
此接口提供验证身份的功能。
public interface CredentialsMatcher {
boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);
}
接口中方法的作用是比较用户输入的的凭证(未加密)与系统提供的凭证(已加密)是否相同,第一个参数是用户输入的身份凭证,第二个参数是系统中保存的用户凭证。
创建MyPasswordService
public interface MyPasswordService extends PasswordService{
//输入明文密码得到加密后的密码
String encryptPassword(Object plaintextPassword) throws IllegalArgumentException;
//匹配用户输入的明文密码和系统提供的密码(已加密) 第一个参数:用户输入的密码,第二个参数:系统提供的密码
boolean passwordsMatch(Object submittedPlaintext, String encrypted);
}
创建MyPasswordServiceImpl
public class MyPasswordServiceImpl implements MyPasswordService{
/**
* 输入明文密码得到加密后的密码,此处使用MD5加密算法,也可使用其它加密算法
*/
@Override
public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException {
Md5Hash md5Hash = new Md5Hash(plaintextPassword);
return md5Hash.toString();
}
/**
* 匹配用户输入的明文密码和系统提供的密码(已加密) 第一个参数:用户输入的密码,第二个参数:系统提供的密码
*/
@Override
public boolean passwordsMatch(Object submittedPlaintext, String encrypted) {
//使用相同的加密算法对用户输入的密码进行加密,然后与系统存在的密码进行比对
Md5Hash md5Hash = new Md5Hash(submittedPlaintext);
if (md5Hash.toString() == encrypted) {
return true;
}
return false;
}
}
创建MD5Realm
public class MD5Realm extends AuthorizingRealm {
private MyPasswordService myPasswordService = new MyPasswordServiceImpl();
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("进入认证");
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("张三", myPasswordService.encryptPassword("123456"),this.getName());
System.out.println("认证结束");
return info;
}
}
测试
这里是直接输入加密后的密码来验证。,一般情况下是用户输入明文密码,经过加密后与数据库中的经过加密的密码进行比对,判断用户信息是否正确。
public class Md5RealmTest {
@Test
public void test1() {
//SecurityManager对象工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory();
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
MD5Realm md5Realm = new MD5Realm();
((RealmSecurityManager) securityManager).setRealm(md5Realm);
Subject subject = SecurityUtils.getSubject();
//封装用户验证信息
AuthenticationToken token = new UsernamePasswordToken("张三", "e10adc3949ba59abbe56e057f20f883e");
try {
subject.login(token);
} catch (Exception e) {
e.printStackTrace();
System.out.println("用户名或密码错误");
}
}
}
运行结果
可以看到用户登陆验证成功。