使用java以及ini文件来测试如何利用散列以及自定义匹配器来测试自定义realm以及如何使用自己的自定义匹配器
自定义realm的项目结构
1、自定义realm,继承 AuthorizingRealm 重写3方法:getName doGetAuthorizationInfo doGetAuthenticationInfo
- 自定义realm
public class MyRealm extends AuthorizingRealm{
@Override
public String getName() {
// TODO Auto-generated method stub
return "MyRealm";//只是个名字 一般项目中有很多realm
}
//授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
return null;
}
//认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(token);
//参数token:表示登录时包装的UsernamePasswordToken
//通过用户名到数据库中查用户信息,封装成一个AuthenticationInfo对象返回,方便认证器进行对比
//获取token中的用户名
String username = (String) token.getPrincipal();
//通过用户名查询数据库,将该用户对应数据查询返回:账号和密码
//假设查询数据库返回数据是:zhangsan 666
if(!"zhangsan".equals(username)){
return null;
}
String password = "666";
//info对象表示realm登录比对信息:参数1:用户信息(真实登录中是登录对象user对象),参数2:密码 参数3:当前realm名字
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
return info;
}
}
- shiro-realm.ini文件内容
#自定义realm
myRealm=cn.com.zhangjh.shiro.MyRealm
##指定SecurityManager的realms实现
securityManager.realms=$myRealm
- 测试类
public class TestShiro {
public static void main(String[] args) {
//1、创建SecurityManager工厂对象,加载配置文件,创建工厂对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = factory.getInstance();
//3、将SecurityManager绑定到当前运行环境中:让系统随时随地都可以访问SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登录的主体、注意:此时主体没有经过认证
Subject subject = SecurityUtils.getSubject();
//5、收集主体登录的身份/凭证,即账号密码
//参数1:将要登录的用户名,参数2:登录用户的密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "666");
//6:主体登录
try {
subject.login(token);
} catch (Exception e) {
//登录失败
e.printStackTrace();
}
//7、判断等是否成功
System.out.println("验证登录是否成功:"+subject.isAuthenticated());
//8:登出(注销)
subject.logout();
System.out.println("验证登录是否成功:"+subject.isAuthenticated());
}
}
shiro加密算法以及自定义匹配器
散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),
比如加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一些md5解密网站很容易的通过散列值得到密码“admin”,
即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。
- 散列值的测试
public class Md5Test {
public static void main(String[] args) {
String password = "666";//密码
//加密:md5
Md5Hash md5Hash = new Md5Hash(password);
//fae0b27c451c728867a567e8c1bb4e53
System.out.println(md5Hash);
//加密:md5 + 盐
md5Hash = new Md5Hash(password,"zhangsan");
//2f1f526e25fdefa341c7a302b47dd9df
System.out.println(md5Hash);
//加密:md5+盐+散列次数
md5Hash = new Md5Hash(password,"zhangsan",3);
//cd757bae8bd31da92c6b14c235668091
System.out.println(md5Hash);
}
}
- 自定义的散列文件
public class PasswordRealm extends AuthorizingRealm{
@Override
public String getName() {
// TODO Auto-generated method stub
return "PasswordRealm";
}
//授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
return null;
}
//认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(token);
//参数token:表示登录时包装的UsernamePasswordToken
//通过用户名到数据库中查用户信息,封装成一个AuthenticationInfo对象返回,方便认证器进行对比
//获取token中的用户名
String username = (String) token.getPrincipal();
//通过用户名查询数据库,将该用户对应数据查询返回:账号和密码
//假设查询数据库返回数据是:zhangsan 666
if(!"zhangsan".equals(username)){
return null;
}
String password = "cd757bae8bd31da92c6b14c235668091";
//info对象表示realm登录比对信息:参数1:用户信息(真实登录中是登录对象user对象),参数2:密码 参数3:盐 参数4:当前realm名字
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password,ByteSource.Util.bytes("zhangsan"), getName());
return info;
}
}
- shiro-realm.ini文件
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=3
#自定义realm
myRealm=cn.com.zhangjh.shiro.PasswordRealm
##指定SecurityManager的realms实现
myRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$myRealm
- 测试类
public class TestShiro {
public static void main(String[] args) {
//1、创建SecurityManager工厂对象,加载配置文件,创建工厂对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = factory.getInstance();
//3、将SecurityManager绑定到当前运行环境中:让系统随时随地都可以访问SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4、创建当前登录的主体、注意:此时主体没有经过认证
Subject subject = SecurityUtils.getSubject();
//5、收集主体登录的身份/凭证,即账号密码
//参数1:将要登录的用户名,参数2:登录用户的密码
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "666");
//6:主体登录
try {
subject.login(token);
} catch (Exception e) {
//登录失败
}
//7、判断等是否成功
System.out.println("验证登录是否成功:"+subject.isAuthenticated());
//8:登出(注销)
subject.logout();
System.out.println("验证登录是否成功:"+subject.isAuthenticated());
}
}