• shiro教程2(自定义Realm)


    通过shiro教程1我们发现仅仅将数据源信息定义在ini文件中与我们实际开发环境有很大不兼容,所以我们希望能够自定义Realm。

    自定义Realm的实现

    创建自定义Realmjava类

    创建一个java文件继承AuthorizingRealm类,重写两个抽象方法

    /**
     * 自定义的Realm
     * @author dengp
     *
     */
    public class MyRealm extends AuthorizingRealm{
    
    	/**
    	 * 认证方法
    	 * @param token 
    	 * 	就是我们在测试代码中 定义的UsernamePasswordToken对象
    	 *  有我们保存的需要验证的账号密码信息
    	 */
    	@Override
    	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    		// 获取账号信息
    		String principal = (String) token.getPrincipal();
    		// 正常逻辑此处应该根据账号去数据库中查询,此处我们默认账号为 root 密码123456
    		// 验证账号
    		if(!"root".equals(principal)){
    			// 账号错误
    			return null;
    		}
    		String pwd = "123456";
    		// 验证密码
    		AuthenticationInfo info = new SimpleAuthenticationInfo(principal, pwd,"myrealm");
    		return info;
    	}
    	
    	/**
    	 * 授权方法
    	 */
    	@Override
    	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    		// TODO Auto-generated method stub
    		return null;
    	}
    }
    
    方法名 说明
    doGetAuthenticationInfo 完成账号认证的方法
    doGetAuthorizationInfo 完成用户授权的方法

    配置ini.xml文件

    [main]
    #自定义 realm
    customRealm=com.dpb.realm.MyRealm
    #将realm设置到securityManager
    securityManager.realms=$customRealm
    

    测试

    测试代码和上个案例一模一样

    @Test
    public void test() {
    	// 1.获取SecurityManager工厂对象
    	Factory<SecurityManager> factory = 
    			new IniSecurityManagerFactory("classpath:shiro.ini");
    	// 2.通过Factory对象获取SecurityManager对象
    	SecurityManager securityManager = factory.getInstance();
    	// 3.将SecurityManager对象添加到当前运行环境中
    	SecurityUtils.setSecurityManager(securityManager);
    	
    	// 4.获取Subject对象
    	Subject subject = SecurityUtils.getSubject();
    	AuthenticationToken token = new UsernamePasswordToken("root1", "12345");
    	// 登录操作
    	try {
    		subject.login(token);
    	} catch (UnknownAccountException e) {
    		System.out.println("账号出错...");
    	} catch(IncorrectCredentialsException e){
    		System.out.println("密码出错...");
    	}
    	// 获取登录的状态
    	System.out.println(subject.isAuthenticated());
    }
    

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    原理分析

    为什么要继承AuthorizingRealm?

    上个教程中我们完整的分析了认证的流程
    我们发现在认证的过程核心代码是此:

    在这里插入图片描述
    核心方法是doGetAuthenticationInfo(token)
    在Realm的结构中
    在这里插入图片描述

    AuthorizingRealm和AuthenticatingRealm都提供的有doGetAuthenticationInfo(token)的抽象方法。
    但是AuthenticatingRealm中要重写的抽象方法太多
    而AuthorizingRealm只需要重写两个方法,且这两个方法都是我们需要使用的。故选择继承AuthorizingRealm

    自定义的Realm什么时候被调用的?

    在这里插入图片描述

    密码验证什么时候执行的?

    注意:自定义Realm中只完成了账号的认证。密码认证还是在AuthenticatingRealm中完成的,只是我们在自定义Realm中完成了密码的设置。

    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    [NOIP2013] 提高组 洛谷P1979 华容道
    Vijos P1404 遭遇战
    CodeVS 1506 传话
    P1546 最短网络 Agri-Net
    HDU 4747 Mex
    POJ1020 Anniversary Cake
    【数据结构】平衡二叉树
    【数据结构】二叉排序树
    【数据结构】二叉树
    概念源于生活
  • 原文地址:https://www.cnblogs.com/dengpengbo/p/10316279.html
Copyright © 2020-2023  润新知