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("没有这个权限");
        }

    }


}
原文地址:https://www.cnblogs.com/fps2tao/p/13570290.html