Shiro的授权和Session管理(三)

戒色诗: 二八佳人体似酥,腰间仗剑斩凡夫。虽然不见人头落,暗里教君骨髓枯。

一. Shiro 的授权

Shiro的授权,主要是对角色和权限进行相关的验证。 注意,对角色和权限验证之前,必须要进行认证, 已经登录成功的用户才可能查询出相应的角色和权限。

首先,老蝴蝶先讲解一下角色,再讲解一下权限。

一.一 Shiro 的角色管理

一.一 .一 提供方法

Shiro 通过 subject 对象里面的方法,对角色进行判断

有图片

方法名 方法解释
boolean hasRole(String paramString) 是否具有某一种角色,返回一个单值
boolean[] hasRoles(List paramList) 是否具有某一些角色,如果具有该角色,就在该角色位置返回true,不具有,则在该位置返回false
boolean hasAllRoles(Collection paramCollection) 是否具有全部角色, 全部具有时才返回true
void checkRole(String paramString) 检查某一个角色,没有该角色,抛出异常
void checkRoles(Collection paramCollection) 检查是否具有一批角色,有一个不符合,就抛出异常
void checkRoles(String... paramVarArgs) 是否具有一批角色,有一个不符合,就抛出异常

一.一 .二 角色测试Demo

一.一 .二.一 创建 shiro_role.ini, 配置角色信息

# 配置用户和角色的信息
[users]
#用户名=密码,角色1,角色2,角色n
yuejl=1234,role1,role3
yuezl=1234,role2

员工yuejl 的密码是 1234, 具有的角色是 role1,role3

员工yuezl 的密码是1234, 具有的角色是 role2

一.一 .二.二 编写测试角色的Demo

角色,常见的有以下几个方面, 是否具有某一种角色,看一些角色里面有哪一些真正具有,是否具有全部的角色等判断。

package com.yjl.role;
import java.util.Arrays;

import org.apache.shiro.SecurityUtils;
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;

/**
 * 
 * @author 两个蝴蝶飞
 * Shiro 角色的测试
 */
public class RoleDemo1 {
	public static void main(String[] args) {
		//1. 创建工厂 
		Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro_role.ini");
		//2. 从工厂里面获取 SecurityManager
		SecurityManager securityManager=factory.getInstance();
		//3. 通过工具类设置 securityManager
		SecurityUtils.setSecurityManager(securityManager);
		
		//4. 获取当前登录的用户
		
		Subject subject=SecurityUtils.getSubject();
		
		//5. 拼装用户的身份和密码Token
		
		//怕乱,不注释写了,后面的程序,只改变这一个 token 代码
		UsernamePasswordToken token=new UsernamePasswordToken("yuejl","1234"); 
		//6. 调用 subject 里面的login 方法,进行登录
		try{			
			subject.login(token);
			
			// 登录成功之后,判断是否具有某个角色		
			boolean flag=subject.hasRole("role1");
			System.out.println(token.getUsername()+"是否具有角色 role1:"+flag);
			flag=subject.hasRole("role2");
			System.out.println(token.getUsername()+"是否具有角色 role2:"+flag);
			
			boolean[] flag2=subject.hasRoles(Arrays.asList("role1","role2","role3"));
			System.out.println("角色:"+Arrays.toString(flag2));
			
			flag=subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
			System.out.println("是否具有所有的角色:"+flag);
			
			//可以用方法 check 进行判断
			try{
				subject.checkRole("role1");
				System.out.println("具有角色role1");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有角色 role1");
			}
			
			try{
				subject.checkRole("role2");
				System.out.println("具有角色role2");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有角色 role2");
			}
			
			try{
				subject.checkRoles(Arrays.asList("role1","role2","role3"));
				System.out.println("具有角色role1,role2,role3");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有角色 role1,role2,role3");
			}

			try{
				subject.checkRoles("role1","role2","role3");
				System.out.println("具有角色role1,role2,role3");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有角色 role1,role2,role3");
			}
			
		}catch (Exception e) {
            e.printStackTrace();
            System.out.println("用户名或者密码错误");
        }
	}
}


运行后,控制台打印输出:

有图片

实际开发中,并不以角色进行相应的判断,而是以具体地权限,进行相应地判断。

一.二 Shiro 的权限管理

一.二.一 提供地权限方法

同样,是通过 subject 对象进行相应的调用 。

有图片

权限方法签名 方法意义
boolean isPermitted(String paramString) 是否具有某个权限,有就返回true,没有则返回false
boolean isPermitted(Permission paramPermission) 是否具有某个权限
boolean[] isPermitted(String... paramVarArgs) 是否具有某一些权限,如果有,则权限对应的数组位置返回true,没有对应位置返回false
boolean[] isPermitted(List paramList) 是否具有某一些权限,如果有,则权限对应的数组位置返回true,没有对应位置返回false
boolean isPermittedAll(String... paramVarArgs) 是否具有所有的权限,可变参数形式
boolean isPermittedAll(Collection paramCollection) 是否具有所有的权限,集合形式
void checkPermission(String paramString) 检查单个权限
void checkPermission(Permission paramPermission) 检查单个权限
void checkPermissions(String... paramVarArgs) 是否具有所有的权限
void checkPermissions(Collection paramCollection) 是否具有所有的权限

在判断权限时,通常使用字符串参数的形式去判断,而不用对象参数形式。

一.二.二 编写测试权限的Demo

一.二.二.一 创建权限文件 shiro_permission.ini

# 配置用户的信息
[users]
#用户名=密码,角色1,角色2
yuejl=1234,role1,role3
yuezl=1234,role2

# 定义角色的信息, 角色,权限, *表示全部的权限
[roles]
role1=user:add,user:delete
role2:user:*
role3:user:select

这是说, role1 具有 user 的add,delete 权限,

role2 具有 user的全部权限

role3 具有 user 的select 查询权限。

一.二.二.二 权限测试小 Demo

package com.yjl.role;
import java.util.Arrays;

import org.apache.shiro.SecurityUtils;
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;

/**
 * 
 * @author 两个蝴蝶飞
 * Shiro 的第五个演示文件, 策略
 */
public class PermissionDemo {
	public static void main(String[] args) {
		//1. 创建工厂 
		Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro_permission.ini");
		//2. 从工厂里面获取 SecurityManager
		SecurityManager securityManager=factory.getInstance();
		//3. 通过工具类设置 securityManager
		SecurityUtils.setSecurityManager(securityManager);
		
		//4. 获取当前登录的用户
		
		Subject subject=SecurityUtils.getSubject();
		
		//5. 拼装用户的身份和密码Token
		
		//怕乱,不注释写了,后面的程序,只改变这一个 token 代码
		UsernamePasswordToken token=new UsernamePasswordToken("yuejl","1234"); 
		//6. 调用 subject 里面的login 方法,进行登录
		try{			
			subject.login(token);
		
			boolean flag=subject.isPermitted("user:add");
			System.out.println(token.getUsername()+" 是否具有权限 user:add ,"+flag);
			
			boolean[] flag2=subject.isPermitted("user:add","user:update","user:select","user:delete");
			
			System.out.println("权限:"+Arrays.toString(flag2));
			
			flag=subject.isPermittedAll("user:add","user:update");
			System.out.println("是否具有全部权限:"+flag);
			
			//也可以检查权限
			try{
				subject.checkPermission("user:add");
				System.out.println("有添加的权限");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有添加的此权限");
			}
			
			try{
				subject.checkPermissions("user:add","user:update");
				System.out.println("有添加和修改的权限");
			}catch(Exception e){
				e.printStackTrace();
				System.out.println("没有添加和修改的此权限");
			}
			
		}catch (Exception e) {
            e.printStackTrace();
            System.out.println("用户名或者密码错误");
        }
	}
	
}

控制台打印输出:

有图片

一.二.三 权限的写法

权限的字符串规则是: 资源标识符:操作:对象实例ID,

如 user:add, user:add:1 这样的形式的。

可以用通配符进行表示。

一.二.三.一 单个资源的单个权限

如user 资源的添加权限, 可以写成: user:add

user 资源的删除权限,可以写成: user:delete

一.二.三.二 单个资源的多个权限

如user 资源的添加和删除权限, 可以写成: user:add,user:delete, 也可以写成: user:add,delete

如果想表示该实例的多个权限, 可以 user:add,delete,update,select, 也可以直接 user:*

一.二.三.三 单个实例的单个权限

需要对每一个具体的实体进行相应的判断,

如对 user 表的编号为1的那个记录的添加权限, 可以 user:add:1

如果是对user 表的那个编号为1的那个记录的删除权限, 可以为 user:delete:1

一.二.三.四 单个实例的多个权限

如对 user表编号为1的那个记录的添加和删除权限, 可以是 user:add,delete:1, 也可以是 user:add:1,user:delete:1

一.二.三.五 单个实例的全部权限

如对 user 表编号为1 的那个记录有全部的权限, 可以是 user:*:1

二. Session 管理

Shiro 也提供了对 Session 的管理, 但一般都用在 Web 端。

通过 subject 对象的 getSession() 方法来获取相应的 Session 对象。

  public abstract Session getSession();

  public abstract Session getSession(boolean paramBoolean);

getSession() 等价于 getSession(true), 表示 如果当前有session()对象,就使用,如果没有,就创建一个。

getSession(false) 表示,如果当前有session()对象,就使用,如果没有,不创建,返回false.

二.一 Session 提供的方法

有图片

但一般都不常用。

二.二 Session 管理的Demo

package com.yjl.role;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;

/**
 * 
 * @author 两个蝴蝶飞
 * Shiro 的第五个演示文件, session管理 
 */
public class SessionDemo {
	public static void main(String[] args) {
		//1. 创建工厂 
		Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro_permission.ini");
		//2. 从工厂里面获取 SecurityManager
		SecurityManager securityManager=factory.getInstance();
		//3. 通过工具类设置 securityManager
		SecurityUtils.setSecurityManager(securityManager);
		
		//4. 获取当前登录的用户
		
		Subject subject=SecurityUtils.getSubject();
		
		//5. 拼装用户的身份和密码Token
		
		//怕乱,不注释写了,后面的程序,只改变这一个 token 代码
		UsernamePasswordToken token=new UsernamePasswordToken("yuejl","1234"); 
		
		Session session=subject.getSession(true);
		
		System.out.println("获取id:"+session.getId());
		
		session.setAttribute("name","两个蝴蝶飞");
		
		String name=(String)session.getAttribute("name");
		System.out.println("输出名称:"+name);

		//6. 调用 subject 里面的login 方法,进行登录
		try{			
			subject.login(token);
			
		}catch (Exception e) {
            e.printStackTrace();
            System.out.println("用户名或者密码错误");
        }
	}
}

获取id 和相应的name 值。

控制台打印输出:

有图片

本章节代码链接为:

链接:https://pan.baidu.com/s/1N-JgSwFGl4IsrBHk-R7cmw 
提取码:w8az

谢谢您的观看,我是两个蝴蝶飞, 如果喜欢,请关注我,再次感谢 !!!

原文地址:https://www.cnblogs.com/yjltx/p/14343152.html