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());
        }
    }

     

  • 相关阅读:
    POJ 1328 Radar Installation
    POJ 1700 Crossing River
    POJ 1700 Crossing River
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3069 Saruman's Army(贪心)
    poj 3069 Saruman's Army(贪心)
    Redis 笔记与总结2 String 类型和 Hash 类型
    数据分析方法有哪些_数据分析方法
    数据分析方法有哪些_数据分析方法
  • 原文地址:https://www.cnblogs.com/wanghj-15/p/11100420.html
Copyright © 2011-2022 走看看