自定义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{@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stubreturn null;}/** 用户自定义认证*/@Overrideprotected 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 {/** 用户认证测试*/@Testpublic void authenticationTest(){//先通过ini对象创建securityManager工厂Factory factory = new IniSecurityManagerFactory("classpath:shiro-myrealm.ini");//通过工厂获取securityManagerSecurityManager 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{@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stubreturn null;}/** 用户自定义认证*/@Overrideprotected 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 {/** 用户认证测试*/@Testpublic void authenticationTest(){//先通过ini对象创建securityManager工厂Factory factory = new IniSecurityManagerFactory("classpath:shiro-myrealmmd5.ini");//通过工厂获取securityManagerSecurityManager 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());}
}
结果