Shiro-菜鸟实战篇-自定义Realm

五迷三道 提交于 2019-12-23 08:56:02
 Realm
      SecuritManager(安全管理器)进行安全认证需要通过Realm获取用户权限数据  
      Realm也是一个接口,有多种实现:
           1、将用户的权限信息写到配置文件
           2、将用户的权限信息存储到数据库
      Realm
           从配置文件或者数据库等读取用户的权限信息

而Shiro自己封装的Realm只能从配置文件读取信息,而用户的认证和授权信息一般存储在关系型数据库中,方便我们维护相关信息。基于这一点,我们可以自定义Realm,下面来分析一下。

自定义Realm-继承 AuthorizingRealm

你要问我为什么要继承AuthorizingRealm?我是不会告诉你的,来看下图继承关系。
在这里插入图片描述
可以看出shiro框架所封装好的方法是new IniRealm(“classpath:xxxx.ini”);
那么,我们下面通过几张图来扒一扒它的"祖宗"。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那么相信你现在懂得为什么要继承AuthorizingRealm了。
现在我们就进行编写自定义的Realm类。

public class ShiroRealm extends AuthorizingRealm {
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
    }
}

自定义Realm-认证实现
编写实体类

public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

编程实现认证的自定义类

public class ShiroRealm extends AuthorizingRealm {

    /*
    登录认证
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        System.out.println("登录认证……");
        //获取用户输入的用户名
        String username = token.getUsername();
        //获取用户输入的密码
        String password = new String(token.getPassword());
        //根据用户名去数据库中查询对应的用户信息
        User user = new User("zhangsan", "123456");
        if (!user.getUsername().equals(username)) {
            throw new UnknownAccountException("用户名有误");
        }
        if (!user.getPassword().equals(password)) {
            throw new CredentialsException("密码有误");
        }
        System.out.println("认证成功");
        //创建简单认证信息对象
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), super.getName());
        return info;
    }

    /*
     授权
    */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        System.out.println("授权……");
        return null;
    }
}

你要问我为什么创建认证信息对象按照下面这种写法,这次我真的不会告诉你,只会告诉你,去看看一个父类子类之间的继承实现关系,你会明白的。

//创建简单认证信息对象
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), super.getName());

看下我们的工具类

public class ShiroUtil {
    static {
        //1.初始化shiro的安全管理器
        DefaultSecurityManager securityManager=new DefaultSecurityManager();
        //2.设置用户的权限信息到安全管理器
       // Realm realm=new IniRealm("classpath:shiro.ini");
        Realm realm=new ShiroRealm();
        securityManager.setRealm(realm);
        //3.使用SecurityUtils将securityManager设置到运行环境中
        SecurityUtils.setSecurityManager(securityManager);
    }
    public static Subject login(String name,String password){
        //4.创建一个Subject实例,该实例认证要使用上面创建的securityManager进行
        Subject subject=SecurityUtils.getSubject();
        //5.创建token令牌,记录用户认证的身份和凭证即证号和密码

        UsernamePasswordToken token=new UsernamePasswordToken(name,password);
        //6.主体要进行登录,登录的时候进行认证的检查
        subject.login(token);
        System.out.println("用户认证状态:"+subject.isAuthenticated());
        return subject;
    }
}

看下我们的测试类

public class ShiroTest {
    @Test
    public void test(){

        Subject subject= ShiroUtil.login("zhangsan","123456");
    }
}

测试一下吧
在这里插入图片描述
可以看出,这时候运行的Realm便是我们自定义的类了。

自定义Realm-授权实现
对ShiroRealm类进行修改

public class ShiroRealm extends AuthorizingRealm {

    /*
    登录认证
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        System.out.println("登录认证……");
        //获取用户输入的用户名
        String username = token.getUsername();
        //获取用户输入的密码
        String password = new String(token.getPassword());
        //根据用户名去数据库中查询对应的用户信息
        User user = new User("zhangsan", "123456");
        if (!user.getUsername().equals(username)) {
            throw new UnknownAccountException("用户名有误");
        }
        if (!user.getPassword().equals(password)) {
            throw new CredentialsException("密码有误");
        }
        System.out.println("认证成功");
        //创建简单认证信息对象
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), super.getName());
        return info;
    }

    /*
     授权
    */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
       //获取主身份信息
        String username=principalCollection.getPrimaryPrincipal().toString();
        /*
        简单授权信息对象,对象中包含用户的角色和权限信息
         */
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //模拟从数据库获取当前用户的角色 通过用户名查询该用户拥有的角色名称
        Set<String>roleNameSet=new HashSet<String>();
        roleNameSet.add("系统管理员");
        roleNameSet.add("系统运维");
        //模拟从数据库获取当前用户的角色 通过用户名查询该用户拥有的权限名称
        Set<String>permissionNameSet=new HashSet<String>();
        permissionNameSet.add("sys:user:list");     //模拟查看列表
        permissionNameSet.add("sys:user:info");     //模拟查看用户详情
        permissionNameSet.add("sys:user:create");   //模拟创建用户
        permissionNameSet.add("sys:user:update");   //模拟修改用户
        permissionNameSet.add("sys:user:delete");   //模拟删除用户
        info.addRoles(roleNameSet);
        info.addStringPermissions(permissionNameSet);
        System.out.println("授权完成");
        return info;
    }
}

对测试类进行修改

public class ShiroTest {
    @Test
    public void test(){
        //登录认证
        Subject subject= ShiroUtil.login("zhangsan","123456");
        //授权资源检查
        //模拟当前用户点击了“新增用户按钮”,检查该用户时候是否新增用户……等等的权限
        System.out.println("检查该用户是否拥有新增用户的权限"+subject.isPermitted("sys:user:create"));
        System.out.println("检查该用户是否拥有删除用户的权限"+subject.isPermitted("sys:user:delete"));
        System.out.println("检查该用户是否拥有喜欢某某某的权限"+subject.isPermitted("你还在么love?true:false"));
        System.out.println("----------------------------------------------");
        System.out.println("检查系统是否有系统管理员角色"+subject.hasRole("系统管理员"));
        System.out.println("检查系统是否有系统运维角色"+subject.hasRole("系统运维"));
        System.out.println("检查系统是否有haosy角色"+subject.hasRole("haosy"));
        //退出系统
        subject.logout();


    }
}

测试
在这里插入图片描述
上文链接:https://haosy.blog.csdn.net/article/details/103612243
下午链接: https://haosy.blog.csdn.net/article/details/103645878
Shiro系列专题链接:https://blog.csdn.net/qq_43518645/category_9604248.html
2019/12/20学习记录。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!