• 第一个Shiro程序


    Shiro 简介

    什么是Shiro

    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证,授权、密码学和会话管理。

    Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
    Authorization:授权,即验证权限,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限。
    Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境的,也可以是Web环境的。
    Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    Web Support:Web支持,可以非常容易的集成到Web环境中
    Caching:缓存,比如用户登录后,其用户信息,拥有的角色/权限不必每次去查,提高效率。
    Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    Testing:提供测试支持
    Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
    Rember Me:记住我,这是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    主要功能

    身份验证、授权、加密、会话

    身份认证

    流程如下:
    1、首先调用 Subject.login(token)进行登录,其会自动委托给 Security Manager,调用之前必
    须通过 SecurityUtils. setSecurityManager()设置;
    2、SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;
    3、Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自
    定义插入自己的实现;
    4、Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认
    ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
    5、Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返
    回/抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进
    行访问。

    Shiro 第一个小程序

    • 添加jar包
    <!---shiro 架包 -->
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
    </dependency>
    
    <!---日记jar包 使用shiro需要使用这jar包 -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
    </dependency>
    
    <!---数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
    </dependency>
    
    <!-- 日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
    </dependency>
    
    
    
    • 配置核心文件
      Shiro 使用的ini文件当做配置文件
      shiro.ini
    #定义用户信息,用户名,或者密码
    [users]
    admin=123
    tom=456
    

    测试

    public static void main(String[] args) {
    
     //第一步 获取Security Manager ,指定配置文件初始化
     IniSecurityManagerFactory factory= new IniSecurityManagerFactory("classpath:shiro01/shiro01.ini");
     SecurityManager securityManager = factory.getInstance();
    
      //第二步 对SecurityManager进行封装,委托给SecurityUtils
    
     SecurityUtils.setSecurityManager(securityManager);
    
     //第三步获取用户主体 Subject
    
    org.apache.shiro.subject.Subject subject=SecurityUtils.getSubject();
     //第四步登录
     UsernamePasswordToken token=new UsernamePasswordToken("admin","123");
    
     //第五步 身份认证 认证成功返回true,认证失败抛出异常
     try {
         //认证前
          // System.out.println("认证之前-是否认证:"+subject.isAuthenticated());
         subject.login(token);
          // System.out.println("认证之后-是否认证:"+subject.isAuthenticated());
         //  System.out.println("调用logout");
         //  subject.logout();
       //  System.out.println("是否认证:"+subject.isAuthenticated());
     } catch (UnknownAccountException e) {
           System.out.println("账户异常:"+e.getMessage());
     }catch (IncorrectCredentialsException e)
     {
         System.out.println("密码异常:"+e.getMessage());
     }
    }
    

    Shiro 默认配置

    在ini核心配置文件中有如下默认配置,SecurityManager、Authenticator 、Authentication、Realm

    #定义用户信息,用户名,或者密码
    [users]
    admin=123
    tom=456
    
    
    #以下默认可以省略#
    
    #默认的SecurityManager
    ##相当于spring容器中定义的bean securityManager 为id  org.apache.shiro.mgt.DefaultSecurityManager 是对应的bean 实现类
     securityManager=org.apache.shiro.mgt.DefaultSecurityManager
    
     # 默认认证器
     authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
     #将认证器添加到SecurityManager中
    securityManager.authentication=$authenticator
    
    # 默认的认证策略
    authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
    #将认证策略添加到认证器中,相当于注入操作,要以$开头
    authenticator.authenticationStrategy=$authenticationStrategy
    
    
    #默认的Realm
    iniRealm=org.apache.shiro.realm.text.IniRealm
    #将Realm添加到SecurityManager中
    securitymanager.realms=$iniRealm
    

    Realm 介绍

    Realm :安全数据源,也就是数据放哪里。

    默认有三种:

    • iniRealm :数据放到ini文件里面
    • JdbcRealm:数据放到数据库里面
    • PropertiesRealm 数据放到Properties文件里面
      iniRealm 使用:
      见第一个shiro例子
      JdbcRealm 使用:
    • 导包
    • 建表
    drop database if exists shiro;
    create database shiro  charset utf8 ;
    use shiro;
    create table t_user
    (
    id int primary key auto_increment,
    login_name varchar(200) not null  unique,
    password varchar(200)
    )engine=Innodb charset utf8;
    
    insert  into t_user(login_name,password)values('admin','111');
    insert into t_user(login_name,password)values('tom','222');
    
    • 工具类
    
    public class ShiroUtils {
    
    
        public static Subject getSubject(String iniPath) {
            //第一步 获取Security Manager ,指定配置文件初始化
            IniSecurityManagerFactory factory = new IniSecurityManagerFactory(iniPath);
            org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
    
            // 第二步 对SecurityManager进行封装委托给SecurityUtils
    
            SecurityUtils.setSecurityManager(securityManager);
    
            //第三步获取用户主体 Subject
    
            org.apache.shiro.subject.Subject subject = SecurityUtils.getSubject();
            return subject;
        }
    }
    
    • 日志文件
    log4j.rootLogger=info,hello
    log4j.appender.hello=org.apache.log4j.ConsoleAppender
    log4j.appender.hello.layout=org.apache.log4j.SimpleLayout
    
    • ini配置文件
    
    #配置数据源
    
    dataSource=com.alibaba.druid.pool.DruidDataSource
    dataSource.driverClassName=com.mysql.jdbc.Driver
    dataSource.url=jdbc:mysql://localhost:3306/shiro?useUnicde=false&characterEncoding=utf-8
    dataSource.username=root
    dataSource.password=123456
    
    # 使用JdbcRealm
    
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
    #注入数据源
    jdbcRealm.dataSource=$dataSource
    #默认sql语句
    #    protected static final java.lang.String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
    #   protected String authenticationQuery = DEFAULT_AUTHENTICATION_QUERY;
    # public void setAuthenticationQuery(String authenticationQuery) {  this.authenticationQuery = authenticationQuery;  }
    #重写认证sql语句
    jdbcRealm.authenticationQuery=select password from t_user where login_name=?
    
    # 将JdbcRealm 添加到SecurityManager
    #securityManager  是默认名   securityManager=org.apache.shiro.mgt.DefaultSecurityManager
    
    securityManager.realms=$jdbcRealm
    
    
    • 测试
    
    public static void main(String[] args) {
    
     Subject subject= ShiroUtils.getSubject("classpath:shiro02/shiro.ini");
    
        UsernamePasswordToken token=new UsernamePasswordToken("admin","111");
        try {
            //认证前
             // System.out.println("认证之前-是否认证:"+subject.isAuthenticated());
            subject.login(token);
             // System.out.println("认证之后-是否认证:"+subject.isAuthenticated());
            //  System.out.println("调用logout");
            //  subject.logout();
         System.out.println("是否认证:"+subject.isAuthenticated());
        } catch (UnknownAccountException e) {
              System.out.println("账户异常:"+e.getMessage());
        }catch (IncorrectCredentialsException e)
        {
            System.out.println("密码异常:"+e.getMessage());
        }catch (AuthenticationException e){
    
              System.out.println(e.getMessage());
        }
    
    }
    

    自定义Realm

    如果使用的是QQ、微信等登陆方式,则需要自定义Realm

    步骤

    • 定义一个类,继承 AuthorizingRealm
    
    public class PropertiesRealm extends AuthorizingRealm {
    
        private String path;
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    
        /*
            *
            * 授权
            * */
        @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            return null;
        }
    
        /*
        *  身份的验证
        * */
        @Override
    
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
    
            //获取token中的用户名
    
            UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
    
            String username = usernamePasswordToken.getUsername();
    
            //查找数据源
    
            Properties p = new Properties();
            try {
    
                if (path.startsWith("classpath:")) {
    
                    path = path.substring(10);
                    p.load(PropertiesRealm.class.getClassLoader().getResourceAsStream(path));
    
                } else if (path.startsWith("file:")) {
                    p.load(new FileInputStream(path));
                }
            } catch (IOException ex) {
                ex.printStackTrace();
    
            }
            String password=p.getProperty("user."+username);
    
            if(password!=null)
            {
    
                  AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
                          username,//用户名
                          password,//数据源中真的真是密码
                          getName()//Reaml 名称
                  );
                return authenticationInfo;
    
            }
    
            return null;
    
    }
    }
    
    
    • 配置文件
    
    
    # 使用自定义Reaml
    
    propertiesRealm= shiro02.realm.PropertiesRealm
    propertiesRealm.path=classpath:shiro02/user.properties
    
    
    # 将JdbcRealm 添加到SecurityManager
    #securityManager  是默认名   securityManager=org.apache.shiro.mgt.DefaultSecurityManager
    
    
    securityManager.realms=$propertiesRealm
    
    

    *属性文件

    
    user.admin=11
    user.tom=666
    
    
  • 相关阅读:
    【翻译】Ext JS最新技巧——2014-9-10
    Ext JS 5的声明式事件监听
    SpringBoot启动方式讲解和部署war项目到tomcat9
    异常处理
    SpringBoot2.x个性化启动banner设置和debug日志
    实用博客
    SpringBootTest单元测试实战、SpringBoot测试进阶高级篇之MockMvc讲解
    SpringBoot注解把配置文件自动映射到属性和实体类实战
    SpringBoot2.x配置文件讲解
    SpringBoot2.x使用Dev-tool热部署
  • 原文地址:https://www.cnblogs.com/lilihai/p/10142108.html
Copyright © 2020-2023  润新知