简单的模拟账号密码登入,为了简便就不去数据库真实的查询了
这里先使用MD5加盐迭代加密,算出我们的密码加密结果
MD5是不可逆的,单向加密,所以我们需要对原始数据进行加密后与加密的数据对比,而不是去解密
package com.test;
import org.apache.shiro.crypto.hash.Md5Hash;
/**
* 对123456加密,
* 盐值(salt):zsl
* 迭代次数:6
* 加密结果:70fc2a964652cf72d7f67022a7951e51
* @author Administrator
*
*/
public class MD5Test {
public static void main(String[] args) {
Md5Hash mdh = new Md5Hash("123456", "zsl", 6);
System.out.println(mdh);
//70fc2a964652cf72d7f67022a7951e51
}
}
自定义的Realm:
认证方法
package com.test;
import java.util.ArrayList;
import java.util.List;
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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.SimpleByteSource;
public class MyRealm extends AuthorizingRealm{
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 获取当前登录的账号
Object principal = principals.getPrimaryPrincipal();
List<String> roleList = new ArrayList<>();
List<String> psList = new ArrayList<>();
roleList.add("role1");
roleList.add("role2");
roleList.add("role3");
psList.add("create");
psList.add("query");
psList.add("delete");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roleList);
info.addStringPermissions(psList);
return info;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
// TODO Auto-generated method stub
//获取账号信息
Object principal = arg0.getPrincipal();
//从数据库等数据源获取数据
String name = "root";
if (!name.equals(principal)) {//低质量的匹配认证
return null;
}
//根据账号去数据库查询出密码
//经过加密加盐迭代后的密码,这里模拟从数据库查询出了已加密的结果
String pwd = "70fc2a964652cf72d7f67022a7951e51";
//我们知道自定义的Realm是不验证密码的,实际验证密码的是AuthenticatingRealm中的AuthenticationInfo方法
//这里的SimpleAuthenticationInfo就是封装好的验证密码的方法
//这里提供了new SimpleByteSource("zsl"),zsl是盐值,而迭代次数在ini中
AuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd,new SimpleByteSource("zsl"), "MyRealm");
return info;
}
}
在没有整合其他框架,如Spring前,我们这里配置ini文件来代替xml以及数据库
Shiro.ini:
[main] #定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法 credentialsMatcher.hashAlgorithmName=md5 #散列次数 credentialsMatcher.hashIterations=1 #将凭证匹配器设置到realm customRealm=com.dpb.realm.MyRealm customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm
测试:
public class Test {
public static void main(String[] args) {
// 获取SecurityManagerFactory对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 根据工厂对象获取SecurityManager对象
SecurityManager manager = factory.getInstance();
// 将SecurityManager添加到运行环境中
SecurityUtils.setSecurityManager(manager);
// 获取Subject对象
Subject subject = SecurityUtils.getSubject();
// 获取对应的认证令牌
AuthenticationToken token = new UsernamePasswordToken("root", "123456") ;
// 做登录认证
try {
subject.login(token);
System.out.println("登录成功....");
} catch (UnknownAccountException e) {
System.out.println("账号错误...");
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误...");
}
System.out.println(subject.isAuthenticated());
}
}
这里是类似于把密码加密加盐迭代后的结果存到数据库,然后客户端请求来的密码是没有加密加盐迭代的,我们需要对它也同样的进行加密加盐迭代,与通过账号到数据库查询出来的密码进行比对。我们知道自定义的Realm是不验证密码的,实际验证密码的是AuthenticatingRealm中的AuthenticationInfo方法去验证密码,所以我们这里自定义的Realm继承AuthorizingRealm重写了doGetAuthenticationInfo方法,这样我们就可以对我们的账号和密码进行相关业务操作。
原文地址:https://www.cnblogs.com/zhangsonglin/p/10983071.html
时间: 2024-10-08 22:22:51