zoukankan      html  css  js  c++  java
  • Shiro -- (三) 自定义Realm

    简介:

      Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。如我们之前的 ini 配置方式将使用 org.apache.shiro.realm.text.IniRealm

    Realm源码:

    public interface Realm {
        String getName();             //返回一个唯一的Realm名字
    
        boolean supports(AuthenticationToken var1);    //判断此Realm是否支持此Token
    
        AuthenticationInfo getAuthenticationInfo(AuthenticationToken var1) throws AuthenticationException;   //根据Token获取认证信息
    }

    一般继承 AuthorizingRealm(授权)即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。其中主要默认实现如下:

      org.apache.shiro.realm.text.IniRealm:[users] 部分指定用户名 / 密码及其角色;[roles] 部分指定角色即权限信息;

      org.apache.shiro.realm.text.PropertiesRealm: user.username=password,role1,role2 指定用户名 / 密码及其角色;role.role1=permission1,permission2 指定角色及权限信息;

      org.apache.shiro.realm.jdbc.JdbcRealm:通过 sql 查询相应的信息,如 “select password from users where username = ?” 获取用户密码,“select password,password_salt from users where username = ?” 获取用户密码及盐;“select role_name from user_roles where username = ?” 获取用户角色;“select permission from roles_permissions where role_name = ?” 获取角色对应的权限信息;也可以调用相应的 api 进行自定义 sql;


    单Realm:

      自己写一个类实现Realm接口

    public class MyRealm implements Realm {
        @Override
        public String getName() {
            return "myrealm";
        }
    
        @Override
        public boolean supports(AuthenticationToken authenticationToken) {
    //仅支持UsernamePasswordToken类型的Token
    return authenticationToken instanceof UsernamePasswordToken; } @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String username = (String)authenticationToken.getPrincipal(); //得到用户名 String password = new String((char[])authenticationToken.getCredentials()); //得到密码 if (!"lc".equals(username)){ throw new UnknownAccountException(); } if (!"123".equals(password)){ throw new IncorrectCredentialsException(); } return new SimpleAuthenticationInfo(username,password,getName()); } }

    shiro-realm.ini

    myrealm=com.lc.demo.MyRealm
    securityManager.realms=$myrealm

    测试:

     @org.junit.Test
        public void t2(){
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-realm.ini");
            SecurityManager securityManager = factory.getInstance();
            SecurityUtils.setSecurityManager(securityManager);
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token=new UsernamePasswordToken("lcc","123");     //账户不正确,验证异常
            try {
                subject.login(token);
            }catch (AuthenticationException e){
                System.out.println("验证失败");
            }
            subject.logout();
        }


    多 Realm 配置

      与上面的类似:两个myrealm

    public class MyRealm2 implements Realm {
        @Override
        public String getName() {
            return "myrealm2";
        }
    
        @Override
        public boolean supports(AuthenticationToken authenticationToken) {
            return authenticationToken instanceof UsernamePasswordToken;
        }
    
        @Override
        public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String username = (String)authenticationToken.getPrincipal();  //得到用户名
            String password = new String((char[])authenticationToken.getCredentials()); //得到密码
            if (!"admin".equals(username)){
                throw new UnknownAccountException();
            }
            if (!"123".equals(password)){
                throw new IncorrectCredentialsException();
            }
            return new SimpleAuthenticationInfo(username,password,getName());
        }
    }

    shiro-multi-realm.ini:

      securityManager 会按照 realms 指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了 Realm 的顺序,如果删“securityManager.realms=$myRealm,$myRealm2”,那么securityManager 会按照 realm 声明的顺序进行使用(即无需设置 realms 属性,其会自动发现),当我们显示指定 realm 后,其他没有指定 realm 将被忽略,如 “securityManager.realms=$myRealm”,那么 myRealm2 不会被自动设置进去。

    myrealm=com.lc.demo.MyRealm
    myrealm2=com.lc.demo.MyRealm2
    securityManager.realms=$myrealm,$myrealm2

    测试:

    @org.junit.Test
        public void t3(){
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
             SecurityManager securityManager = factory.getInstance();
             SecurityUtils.setSecurityManager(securityManager);
                 Subject subject = SecurityUtils.getSubject();
                 UsernamePasswordToken token=new UsernamePasswordToken("lc","123");
                 UsernamePasswordToken token2=new UsernamePasswordToken("admin","123");
                 try {
                 subject.login(token);
                 subject.login(token2);
             }catch (AuthenticationException e){
                 System.out.println("nonono!");
             }
             subject.logout();
         }
  • 相关阅读:
    Linq To Object
    笔试算法
    给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线
    vue3.0中setup的参数
    力扣算法题
    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组
    vif 与 vfor优先级
    给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 /返回这三个数的和。
    /给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[
    vue3+canvas随机生成4位验证码
  • 原文地址:https://www.cnblogs.com/crazy-lc/p/12372262.html
Copyright © 2011-2022 走看看