勿以恶小而为之,勿以善小而不为--------------------------刘备
劝诸君,多行善事积福报,莫作恶
上一章简单介绍了 Shiro的Jdbc配置和验证策略(二),如果没有看过,请观看上一章
一. 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
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!