shiro权限框架学习二(自定义Realm,MD5加密,加盐加密)

自定义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());
		
	}
}

结果

猜你喜欢

转载自blog.csdn.net/baiyan3212/article/details/85156489
今日推荐