zoukankan      html  css  js  c++  java
  • Apache Shiro初认识

    Apache Shiro

    一、Shiro介绍:

           Apache软件基金会专门针对系统中的登录、加密、权限认证、授权等等功能进行了封装,不仅仅适用于JavaWeb项目,CS架构的系统也可以使用Shiro。

      Apache Shiro是一个强大且易用的Java安全框架,有身份验证、授权、密码学(加密)会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

     

    相同的产品:  

      Spring security 重量级安全框架。

      Apache Shiro 轻量级安全框架。

     

     

    二、Shiro的使用

      前提:创建一个普通的Maven项目。

      准备(导包):配置Shiro需要的jar包

    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

      1、密码加密

      注意:加密方式一般有 MD5 和 SHA 两种,下面测试使用的是MD5加密方式

        MD5加密方式特点:只能加密,不能解密。(在数据库中保存的密码都是加密过后的密码,使用MD5加密方式的话,登录的密码在登录之前都要先进行加密,因此必须保证登录前的加密规则要和数据库中密码的加密规则相同(加密规则:加密方式、盐值、加密次数))

    public class ShiroTest extends BaseTest {
    
        @Test
        public void test() throws Exception {
    
            String password = "123";
    
            /**
             * String algorithmName
             *  加密方式: MD5 和 SHA 两种
             * Object source
             *  要加密的内容  [一般填密码字符串]
             * Object salt
             *  盐值[一般也是填字符串]
             * int hashIterations
             *  加密次数
             */
            SimpleHash simpleHash = new SimpleHash("MD5", password,"wang",10);
    
    
            //MD5加密方式的结果:32位十六进制的数字组成的字符串
            System.out.println(simpleHash);
    
        }
    
        /**
         * 测试:将数据库中的密码进行加密
         * 为了防止记不住密码,先在数据库中执行 update employee set password = username;
         */
        @Autowired
        private IEmployeeService employeeService;
        @Test
        public void testUpdateAllPassword() throws Exception {
            SimpleHash simpleHash = null;
            List<Employee> list = employeeService.findByJPQL("from Employee e");
            for (Employee employee : list) {
                simpleHash = new SimpleHash("MD5", employee.getUsername(),"wang",10);
                //重新设置加密之后的密码
                employee.setPassword(simpleHash.toString());
                //保存数据【更新】
                employeeService.save(employee);
            }
        }
    
    }

      2、登录验证

      2.1 准备 .ini 文件类型的数据(在ini文件中,#代表注释)

    # -----------------------------------------------------------------------------
    # 所有用户数据以及他属于哪些角色
    #   root = 123, admin, schwartz
    #       root表示用户名    123是密码    admin是root这个用户属于哪个角色
    # -----------------------------------------------------------------------------
    [users]
    root = 123, admin
    guest = 123, schwartz
    presidentskroob = 123, president
    darkhelmet = 123, darklord, schwartz
    lonestarr = 123, goodguy, schwartz
    
    # -----------------------------------------------------------------------------
    # 所有角色以及对应的权限
    #   admin = *  admin是角色名称   *表示他拥有所有权限
    #   schwartz = employee:*   schwartz是角色名称   employee:* 表示schwartz角色具备的权限:/employee/*
    #   goodguy = department:save   goodguy是角色名称    department:save 表示goodguy角色具备的权限:/department/save
    # -----------------------------------------------------------------------------
    [roles]
    admin = *
    schwartz = employee:*
    goodguy = department:save

      2.2 测试登录验证

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.junit.Test;
    
    public class ShiroTest {
    
        /**
         * 1)准备资源【数据--ini配置文件来准备】
         * 2)创建SecurityManager对象
         *      读取ini文件【正式项目要换成数据库查询】得到一个工厂对象
         *      通过工厂创建一个SecurityManager对象
         *      将SecurityManager对象放入Shiro的上下文中
         *      获取当前用户
         *          判断是否已经登录 isAuthenticated()
         *          登录【login 传入一个UsernamePasswordToken】
         *          是否属于某个角色【hasRole】
         *          是否拥有某些权限【isPermitted】
         *          退出【logout()】
         * @throws Exception
         */
        @Test
        public void test() throws Exception {
    
            //读取shiro.ini文件数据,生成一个SecurityManager工厂对象
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //通过工厂创建一个SecurityManager对象
            SecurityManager securityManager = factory.getInstance();
    
            //将SecurityManager对象放入Shiro的上下文中
            SecurityUtils.setSecurityManager(securityManager);
    
            //获取当前用户【不论你是否已经登录,只要你访问就认为你是一个用户】
            Subject currentUser = SecurityUtils.getSubject();
    
            System.out.println("判断用户root是否已经登录:" + currentUser.isAuthenticated());
    
            //准备一个令牌【包含用户名和密码,模拟项目中的前端登录表单提交过来的请求参数】
            UsernamePasswordToken token = new UsernamePasswordToken("root","123");
            try {
                if(!currentUser.isAuthenticated()){
                    //用户登录
                    currentUser.login(token);
                }
            } catch (UnknownAccountException e){
                //UnknownAccountException:表示用户名不存在;   Unknown(未知的)  Account(账户、用户名)
                e.printStackTrace();
                System.out.println("登录失败-用户名不存在!");
            } catch (IncorrectCredentialsException e){
                //IncorrectCredentialsException :表示密码错误;  Incorrect(不正确的)  Credentials(凭证、密码)
                e.printStackTrace();
                System.out.println("登录失败-密码错误!");
            } catch (AuthenticationException e) {
                e.printStackTrace();
            }
    
            System.out.println("判断用户root是否已经登录:" + currentUser.isAuthenticated());
    
            //判断root用户是否属于某个角色
            System.out.println("判断root用户是否属于admin角色:" + currentUser.hasRole("admin"));
            System.out.println("判断root用户是否属于itsource角色:" + currentUser.hasRole("itsource"));
            System.out.println("判断root用户是否属于guest角色:" + currentUser.hasRole("guest"));
    
            //判断root用户是否拥有某些权限
            System.out.println("判断root用户是否拥有所有权限:" + currentUser.isPermitted("*"));
            System.out.println("判断root用户是否拥有employee:*权限:" + currentUser.isPermitted("employee:*"));
    
            //用户退出系统
            currentUser.logout();
    
            System.out.println("判断用户root是否已经登录:" + currentUser.isAuthenticated());
        }
    }

     

  • 相关阅读:
    个人理财小助手 —— 简介
    我的分页控件(未完,待续)——控件件介绍及思路
    静态变量 静态对象 静态函数和非静态函数的区别。(我的理解,大家看看对不对)
    通过“访问多种数据库”的代码来学习多态!(.net2.0版)
    Step By Step 一步一步写网站[1] —— 填加数据
    个人理财小助手 —— 数据库(一)
    几个鸟叫的声音
    Step By Step 一步一步写网站[1] —— 帧间压缩,表单控件
    面向对象相关
    论程序的成长—— 你写的代码有生命力吗?
  • 原文地址:https://www.cnblogs.com/wanghj-15/p/11100420.html
Copyright © 2011-2022 走看看