• 30、shiro框架入门2,关于Realm


    1、Jdbc的Realm链接,并且获取权限

    首先创建shiro-jdbc.ini的配置文件,主要配置链接数据库的信息

    配置文件中的内容如下所示

    1、变量名=全限定类名会自动创建一个类实例

    2、变量名.属性=值 自动调用相应的setter方法进行赋值

    3、$变量名 引用之前的一个对象实例 

    4、测试代码请参照com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest的testJDBCRealm方法,和之前的没什么区别。

      到数据库shiro下建三张表:users(用户名/密码)、user_roles(用户/角色)、roles_permissions(角色/权限),具体请参照shiro-example-chapter2/sql/shiro.sql;并添加一个用户记录,用户名/密码为zhang/123;

    USE shiro;
    
    CREATE TABLE users (
      id BIGINT AUTO_INCREMENT,
      username VARCHAR(100),
      PASSWORD VARCHAR(100),
      password_salt VARCHAR(100),
      CONSTRAINT pk_users PRIMARY KEY(id)
    ) CHARSET=utf8 ENGINE=INNODB;
    CREATE UNIQUE INDEX idx_users_username ON users(username);
    
    CREATE TABLE user_roles(
      id BIGINT AUTO_INCREMENT,
      username VARCHAR(100),
      role_name VARCHAR(100),
      CONSTRAINT pk_user_roles PRIMARY KEY(id)
    ) CHARSET=utf8 ENGINE=INNODB;
    CREATE UNIQUE INDEX idx_user_roles ON user_roles(username, role_name);
    
    CREATE TABLE roles_permissions(
      id BIGINT AUTO_INCREMENT,
      role_name VARCHAR(100),
      permission VARCHAR(100),
      CONSTRAINT pk_roles_permissions PRIMARY KEY(id)
    ) CHARSET=utf8 ENGINE=INNODB;
    CREATE UNIQUE INDEX idx_roles_permissions ON roles_permissions(role_name, permission);
    
    INSERT INTO users(username,PASSWORD)VALUES('zhang','123');

    然后就是单元测试的过程,java通过读取realm-jdbc.ini文件获取权限,角色,用户名称等

    @Test
        public void testJDBCRealm() {
            //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
            Factory<org.apache.shiro.mgt.SecurityManager> factory =
                    new IniSecurityManagerFactory("classpath:shiro-jdbc.ini");
            //2、得到SecurityManager实例 并绑定给SecurityUtils
            org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
            SecurityUtils.setSecurityManager(securityManager);
          //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
    
            try {
                //4、登录,即身份验证
                subject.login(token);
            } catch (AuthenticationException e) {
            }
    
            Assert.assertEquals(true, subject.isAuthenticated()); 
            //6、退出
            subject.logout();
        }

    二、

    Authenticator及AuthenticationStrategy

    Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 

    public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
                throws AuthenticationException;&nbsp;

    如果验证成功,将返回AuthenticationInfo验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的AuthenticationException实现。

    SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:

    FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;

    AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;

    AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

    ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略。

    [main]
    
    #指定securityManager的authenticator实现  
    authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator  
    securityManager.authenticator=$authenticator  
    #指定securityManager.authenticator的authenticationStrategy  
    allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy  
    securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy
    myRealm1=realm.MyRealm1  
    myRealm2=realm.MyRealm2
    securityManager.realms=$myRealm1,$myRealm2 
    package realm;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.realm.Realm;
    
    public class MyRealm2 implements Realm{
    
        public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
            String username=(String)token.getPrincipal();//得到用户名
            String password=new String((char[])token.getCredentials());//得到密码
            if(!"zhang".equals(username)){
                throw new UnknownAccountException();//如果用户名错误
            }
            if(!"123".equals(password)){
                throw new IncorrectCredentialsException();//如果密码错误
            }
            //如果身份认证成功,返回一个AuthenticationInfo实现;
            return new SimpleAuthenticationInfo("zhang@163.com", "123", getName());
        }
    
        public String getName() {
            return "myrealm2";
        }
    
        public boolean supports(AuthenticationToken token) {
            //仅支持UsernamePasswordToken类型的Token  
            return token instanceof UsernamePasswordToken;
        }
    
    }
    package realm;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.realm.Realm;
    
    public class MyRealm1 implements Realm{
    
        public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
            String username=(String)token.getPrincipal();//得到用户名
            String password=new String((char[])token.getCredentials());//得到密码
            if(!"zhang".equals(username)){
                throw new UnknownAccountException();//如果用户名错误
            }
            if(!"123".equals(password)){
                throw new IncorrectCredentialsException();//如果密码错误
            }
            //如果身份认证成功,返回一个AuthenticationInfo实现;
            return new SimpleAuthenticationInfo(username, password, getName());
        }
    
        public String getName() {
            return "myrealm1";
        }
    
        public boolean supports(AuthenticationToken token) {
            //仅支持UsernamePasswordToken类型的Token  
            return token instanceof UsernamePasswordToken;
        }
    
    }

    @Test
    	public void testMoreAuthention() {
    		login("classpath:shiro-authenticator-all-success.ini");
    		Subject subject = SecurityUtils.getSubject();  
    		 //得到一个身份集合,其包含了Realm验证成功的身份信息 
    		PrincipalCollection collection=subject.getPrincipals();
    		Assert.assertEquals(2, collection.asList().size());
    	}
    

      最后测试好像不太好使

    login方法

    public void login(String config){
            System.out.println(config);
            Factory<org.apache.shiro.mgt.SecurityManager> factory=
                    new IniSecurityManagerFactory(config);
            org.apache.shiro.mgt.SecurityManager manager = (org.apache.shiro.mgt.SecurityManager) factory.getInstance();
            SecurityUtils.setSecurityManager(manager);
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
            subject.login(token);
        }
  • 相关阅读:
    博客搬迁
    android中listview的item滑动删除效果(已解决listview点击问题)
    来把博客园变成“原谅”的颜色
    Datatables后台服务器端分页、根据条件重新查询、主要技术问题
    JQuery双列表交互模态窗口,列表项互相、上下移动
    Angular页面刷新保存变量数据,运用localstorage
    Angular中使用datatable.js出现错误“ui-router TypeError: Cannot read property 'childNodes' of undefined”的解决方法
    使用swiper-animate.js制作h5宣传页
    使用JavaScript/JQuery 操作SVG元素的几个关键技巧
    mac os系统使用Visual Studio Code打开浏览器查看HTML文件
  • 原文地址:https://www.cnblogs.com/weizhen/p/5947848.html
Copyright © 2020-2023  润新知