• Shiro教程之二Shiro.ini认证和授权


    1,Shiro.ini文件的说明

    1. ini (InitializationFile) 初始文件.Window系统文件扩展名.

    2. Shiro 使用时可以连接数据库,也可以不连接数据库.

            2.1 如果不连接数据库,可以在shiro.ini中配置静态数据

    2,Shrio.ini文件的组成部分

    1,[main] :定义全局变量

    [main]
    securityManager.属性=值            <property name=”属性名” value=””
    myobj=com.bjsxt.Obj            <bean id=”myobj” class=”com.bjsxt.Obj”
    securityManager.对象属性=$myobj   <property name=”属性名” ref=” myobj”

    2,[users] :定义用户名和密码

    [users]
    # 定义用户名为zhangsan 密码为zs
    zhangsan=zs
    # 定义用户名lisi密码为lisi同时具有role1和role2两个角色
    lisi=lisi,role1,role2

    3,[roles]: 定义角色

    [roles]
    role1=user:query,权限名2 
    role2=权限3,权限4

    4,[urls] : 定义哪些内置urls生效.在web应用时使用.

    [urls]
    #url地址=内置filter或自定义filter
    # 访问时出现/login的url必须去认证.支持authc对应的Filter
    /login=authc
    # 任意的url都不需要进行认证等功能.
    /** = anon
    # 所有的内容都必须保证用户已经登录.
    /**=user
    # url abc 访问时必须保证用户具有role1和role2角色.
    /abc=roles[“role1,role2”]
    /login.html*=anon
    /loginOut*=logout
    /**= authc  所有URL必须认证通过之后才能放行  一般放到最后

    3【掌握】Shiro.ini实现认证和授权

    1,基本概念

    1,身份验证
            即在应用中谁能证明他就是他本人。一般提供如他们的身份ID 一些标识信息来
    表明他就是他本人,如提供身份证,用户名/密码来证明。
            在 shiro 中,用户需要提供principals (身份)和credentials(证明)给shiro,从而应用能
    验证用户身份:
    2,principals 【/'prɪnsəpl】
            身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。
    一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。
    3,credentials 【/krə'dɛnʃlz/】
            证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
            最常见的principals和credentials组合就是用户名/密码了。接下来先进行一个基本的身份认证。

    2,认证流程

    其它就是使用Shrio的认证来取代我们传统的登陆方式

     

    3,入门程序实现认证

      1.      创建项目(引入jar包或maven依赖)

      2.      创建shiro.ini(类路径或最后可以编译到类路径的目录)

    #配置用户
    [users]
    zhangsan=123456
    lisi=123456
    wangwu=123456

      3.      写代码测试 (认证)

    package com.cc8w.test;
    
    
    
    import com.cc8w.shiro.ShiroRealm;
    import org.apache.log4j.Logger;
    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.authz.AuthorizationException;
    import org.apache.shiro.authz.UnauthenticatedException;
    import org.apache.shiro.authz.UnauthorizedException;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.Arrays;
    
    /**
     *
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class TestShiro {
        private static Logger logger = Logger.getLogger(TestShiro.class);
    
        @Autowired
        private ShiroRealm shiroRealm;
    
        public static void main(String[] args) {
            TestShiro ts = new TestShiro();
            ts.testAuth();
    
    
        }
    
        //一,登录测试(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置)
        @Test
        public void testlogin(){
            //1.创建一个安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2.在工厂中获取安全管理器
            SecurityManager securityManager = factory.getInstance();
            //3.将securityManager绑定到运行环境
            SecurityUtils.setSecurityManager(securityManager);
            //4.获取Subject对象(将要登录的用户)
            Subject subject = SecurityUtils.getSubject();
            //5.获取要登录用户的token,客户端传递过来的用户名和密码
            String username = "zhangsan",password="123456";
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    
            try{
                subject.login(token);
                logger.info("登录了");
    
            }catch (IncorrectCredentialsException  e ){
                logger.info("密码不正确");
                logger.info(e);
            }catch (UnknownAccountException e) {
                System.out.println("没有这个帐号");
            }catch (AuthenticationException e) {
                e.printStackTrace();
            }
    
            //如果登录成功了,可以获取subject中各种状态了
            Boolean isAuth = subject.isAuthenticated();
            logger.info(isAuth);
            try {
                subject.checkRole("roles");
            }catch (UnauthenticatedException e){
                logger.info("没有这个角色");
                e.printStackTrace();
            }
    
        }
    
    
    
    
    }

     相关方法总结

    1,  注意Subject的或取方式

    2,  注意使用异常方式确定登陆是否成功

    ==========================

    4【掌握】shiro.ini实现授权

    1,授权概述

    授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作
    
    等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、
    
    角色(Role)。
     

    2,关键对象介绍

    1,主体
    主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。
    2,资源
    在应用中用户可以访问的任何东西,比如访问JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。
    3,权限
    安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,
    如:访问用户列表页面查看
    /新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)打印文档等等。。。 4,角色 角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。
    典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。

    3,授权流程

    4,相关方法说明

    1 subject.hasRole(“”); 判断是否有角色
    
    2 subject.hashRoles(List);分别判断用户是否具有List中每个内容
    
    3 subject.hasAllRoles(Collection);返回boolean,要求参数中所有角色用户都需要具有.
    
    4 subject.isPermitted(“”);判断是否具有权限.

    5,修改shiro.ini

    #配置用户
    [users]
    zhangsan=123456,role1
    lisi=123456,role2,role4
    wangwu=123456,role3
    zhaoliu=123456,role4
    
    #配置角色和权限
    [roles]
    role1=user:query,user:add,user:update,user:delete,user:export
    role2=user:query
    role3=user:query,user:add
    role4=user:query,user:export

    6,权限标识符号规则

    权限标识符号规则:资源:操作:实例(中间使用半角:分隔)
    user:create:01 表示对用户资源的01实例进行create操作。
    user:create:表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。
    user:*:01 表示对用户资源实例01进行所有操作。

    7,测试代码 (因为测试授权时必须登录,所以下认证登录)

    package com.cc8w.test;
    
    import com.cc8w.shiro.ShiroRealm;
    import org.apache.log4j.Logger;
    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.authz.AuthorizationException;
    import org.apache.shiro.authz.UnauthenticatedException;
    import org.apache.shiro.authz.UnauthorizedException;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.Arrays;
    
    /**
     *
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class TestShiro {
        private static Logger logger = Logger.getLogger(TestShiro.class);
    
        @Autowired
        private ShiroRealm shiroRealm;
    
        public static void main(String[] args) {
            TestShiro ts = new TestShiro();
            ts.testAuth();
    
    
        }
    
        //一,登录测试(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置)
        @Test
        public void testlogin(){
            //1.创建一个安全管理器的工厂
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2.在工厂中获取安全管理器
            SecurityManager securityManager = factory.getInstance();
            //3.将securityManager绑定到运行环境
            SecurityUtils.setSecurityManager(securityManager);
            //4.获取Subject对象(将要登录的用户)
            Subject subject = SecurityUtils.getSubject();
            //5.获取要登录用户的token,客户端传递过来的用户名和密码
            String username = "zhangsan",password="123456";
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    
            try{
                subject.login(token);
                logger.info("登录了");
    
            }catch (IncorrectCredentialsException  e ){
                logger.info("密码不正确");
                logger.info(e);
            }catch (UnknownAccountException e) {
                System.out.println("没有这个帐号");
            }catch (AuthenticationException e) {
                e.printStackTrace();
            }
    
            //如果登录成功了,可以获取subject中各种状态了
            Boolean isAuth = subject.isAuthenticated();
            logger.info(isAuth);
            try {
                subject.checkRole("roles");
            }catch (UnauthenticatedException e){
                logger.info("没有这个角色");
                e.printStackTrace();
            }
    
        }
        //二.授权验证(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置)
        @Test
        public void testAuth(){
            String username = "zhangsan",password="123456";
            //1.创建securityManager工厂SecurityManager JDK也有这个类,在java.lang包,注意不要使用jdk里面的类
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            //2,从工厂中获取SecurityManager
            SecurityManager securityManager = factory.getInstance();
            //3,把当前的SecurityManager绑定到当前线程中
            SecurityUtils.setSecurityManager(securityManager);
            //4,取出当前的Subject
            Subject subject = SecurityUtils.getSubject();
    
            //5.创建token用于认证 客户端传递过来的用户名和密码
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
            //6.登录认证
            try{
                subject.login(token);
                System.out.println("登录成功");
            }catch (IncorrectCredentialsException  e){
                System.out.println("密码不正确");
            }catch (UnknownAccountException e){
                System.out.println("无此账号");
            }catch (AuthenticationException e) {
                e.printStackTrace();
            }
            System.out.println("认证状态:"+subject.isAuthenticated());
    
            //7.授权 基于角色授权 基于资源的授权
    
            //7.1 基于角色授权
            boolean isRole1 = subject.hasRole("role1");
            System.out.println("这是授权单个: "+isRole1);
    
            boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
            System.out.println("这是多个授权:" + hasAllRoles);
    
            // 使用check方法进行授权,如果授权不通过会抛出异常
            // subject.checkRole("role13");
    
    
            // 7.2 基于资源的授权
            // isPermitted传入权限标识符
            boolean isPermitted = subject.isPermitted("user:query");
            System.out.println("单个权限判断user:query->"+isPermitted);
            boolean isPermittedAll = subject.isPermittedAll("user:query","user:add","user:del");
            System.out.println("多个权限判断"+isPermitted);
    
            // 使用check方法进行授权,如果授权不通过会抛出异常
            try{
                subject.checkPermission("items:create:1");
            }catch (UnauthorizedException e){
                // e.printStackTrace();
                System.out.println("没有这个权限");
            }
    
        }
    
    
    }
  • 相关阅读:
    android 限定符参考
    Fragment生命周期
    碎片和活动之间通信
    Fragment碎片的使用
    使用Intent传值及回传值
    Calendar 获取年 月 日 时 分 秒
    Python函数:2018-07-30
    Python 字符串 2018-07-27
    Python 异常 2018-08-01
    __future__ 模块 2018-08-09
  • 原文地址:https://www.cnblogs.com/fps2tao/p/13570290.html
Copyright © 2020-2023  润新知