自定义Realm
realm:需要根据token中的身份信息去查询数据库(入门程序使用ini配置文件),如果查到用户返回认证信息,如果查询不到返回null。token就相当于是对用户输入的用户名和密码的一个封装。下面就是创建一个用户名密码token:
UsernamePasswordToken token = new UsernamePasswordToken("xuxu01", "123456");
Realm结构:
自定义Realm
package com.xuxu.realm;
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;
public class MyRealm extends AuthorizingRealm{
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
/*
* 用户自定义认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//第一步从token中取出身份信息(token代表用户输入的传下来的信息)
String userName = (String) token.getPrincipal();
//第二步:根据用户输入的userCode从数据库查询
//数据库中通过名称查询出对应的用户信息
//判断数据库中查出用户是否为空
//假设数据库中查出用户账号密码为
String name = "xuxu01";
String password="123456";
SimpleAuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(name, password, this.getName());
return authenticationInfo;
}
}
配置自定义Realm
需要在shiro-myrealm.ini配置realm注入到securityManager中。
[main]
#自定义realm
myRealm=com.xuxu.realm.MyRealm
#将myRealm设置进securityManager 相当于spring中注入自定义realm
securityManager.realms=$myRealm
测试java代码
package com.xuxu;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
public class AuthenticationTest2_myRealm {
/*
* 用户认证测试
*/
@Test
public void authenticationTest(){
//先通过ini对象创建securityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-myrealm.ini");
//通过工厂获取securityManager
SecurityManager securityManager = factory.getInstance();
//将securityManager设入本地SecurityUtils中
SecurityUtils.setSecurityManager(securityManager);
//获取用户主体就是请求方
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("xuxu01","123456");
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
//判断是否登录成功
System.out.println(subject.isAuthenticated());
//登出
subject.logout();
System.out.println("退出登录");
System.out.println(subject.isAuthenticated());
}
}
结果
自定义Realm 支持MD5加盐验证
MD5工具类
package com.xuxu.util;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
public class Md5Util {
//构造方法中:
//第一个参数:明文,原始密码
//第二个参数:盐,通过使用随机数
//第三个参数:散列的次数,比如散列两次,相当 于md5(md5(''))
public static String md5Password(String source, String salt, int hashIterations){
Md5Hash md5Hash = new Md5Hash(source, salt, hashIterations);
String password_md5 = md5Hash.toString();
return password_md5;
}
//第一个参数:散列算法
public static String md5Password(String algorithmName ,String source, String salt, int hashIterations){
SimpleHash simpleHash = new SimpleHash(algorithmName, source, salt, hashIterations);
String password_md5 = simpleHash.toString();
return password_md5;
}
public static void main(String[] args) {
//原始 密码
String source = "123456";
//盐
String salt = "3333";
//散列次数
int hashIterations = 2;
String password_md5 = md5Password(source,salt,hashIterations);
System.out.println(password_md5);
// 第二种方法
password_md5 = md5Password("md5",source,salt,hashIterations);
System.out.println(password_md5.toString());
//e5d2f047db39bac635faa95377be2de9
//e5d2f047db39bac635faa95377be2de9
}
}
原始密码为123456 盐为3333 散列次数2次后结果为
e5d2f047db39bac635faa95377be2de9
这个后期做为密码存入数据库中
自定义Realm
public class MyRealmMd5 extends AuthorizingRealm{
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
/*
* 用户自定义认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//第一步从token中取出身份信息(token代表用户输入的传下来的信息)
String userName = (String) token.getPrincipal();
//第二步:根据用户输入的userCode从数据库查询
//数据库中通过名称查询出对应的用户信息
//判断数据库中查出用户是否为空
//假设数据库中查出用户账号密码为
String name = "xuxu01";
String password="e5d2f047db39bac635faa95377be2de9";
String salt = "3333";
SimpleAuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(name, password,ByteSource.Util.bytes(salt),this.getName());
return authenticationInfo;
}
}
其中数据库中查询出来的密码为加盐散列后的密码e5d2f047db39bac635faa95377be2de9
在查询认证信息时 将盐传入ByteSource.Util.bytes(salt) 如果没有加盐就不需要这个参数
配置文件 shiro-myrealmmd5.ini
[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=2
#将凭证匹配器注入到realm
myRealm=com.xuxu.realm.MyRealmMd5
myRealm.credentialsMatcher=$credentialsMatcher
#将myRealm设置进securityManager 相当于spring中注入自定义realm
securityManager.realms=$myRealm
测试类
public class AuthenticationTest3_myRealmMd5 {
/*
* 用户认证测试
*/
@Test
public void authenticationTest(){
//先通过ini对象创建securityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-myrealmmd5.ini");
//通过工厂获取securityManager
SecurityManager securityManager = factory.getInstance();
//将securityManager设入本地SecurityUtils中
SecurityUtils.setSecurityManager(securityManager);
//获取用户主体就是请求方
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("xuxu01","123456");
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
//判断是否登录成功
System.out.println(subject.isAuthenticated());
//登出
subject.logout();
System.out.println("退出登录");
System.out.println(subject.isAuthenticated());
}
}