Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权

Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权

一、Shiro授权:

1、授权与权限:

(1)授权:访问控制,必须具有该资源的访问权限才可以访问该资源。

(2)权限模型:标准权限数据模型包括 :用户、角色、权限(包括资源和权限)、用户角色关系、角色权限关系。

(3)权限分配:通过UI界面方便给用户分配权限,对上边权限模型进行增、删、改、查操作。

(4)权限控制:

第一种:基于角色的权限控制:根据角色判断是否有操作权限,因为角色的变化性较高,如果角色修改需要修改控制代码,系统可扩展性不强。

第二种:基于资源的权限控制:根据资源权限判断是否有操作权限,因为资源较为固定,如果角色修改或角色中权限修改不需要修改控制代码,使用此方法系统可维护性很强。建议使用。

(5)权限管理的解决方案:

①对于粗颗粒权限管理,建议在系统架构层面去解决,写系统架构级别统一代码(基础代码)。

粗颗粒权限:比如对系统的url、菜单、jsp页面、页面上按钮、类方法进行权限管理,即对资源类型进行权限管理。

②对于细颗粒权限管理:细颗粒权限管理是系统的业务逻辑,业务逻辑代码不方便抽取统一代码,建议在系统业务层进行处理。

粗颗粒权限:比如用户id为001的用户信息(资源实例)、类型为t01的商品信息(资源实例),对资源实例进行权限管理,可以理解为对数据级别的权限管理。

 

2、授权流程:

(1)对subject进行授权,调用方法isPermitted(”permission串”);

(2)SecurityManager执行授权,通过ModularRealmAuthorizer执行授权;

(3)ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据,调用realm的授权方法:doGetAuthorizationInfo;

(4)realm从数据库查询权限数据,返回ModularRealmAuthorizer;

(5)ModularRealmAuthorizer调用PermissionResolver进行权限串比对;

(6)如果比对后,isPermitted中”permission串”在realm查询到权限数据中,说明用户访问permission串有权限,否则 没有权限,抛出异常。

Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权

 

3、Shiro 支持三种方式的授权:

(1)编程式:通过写if/else 授权代码块完成:

Subject subject = SecurityUtils.getSubject();

if(subject.hasRole(“admin”)) {

//有权限

} else {

//无权限

}

(2)注解式:通过在执行的Java方法上放置相应的注解完成:

@RequiresRoles(“admin”)

public void hello() {

//有权限

}

(3)JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:

<shiro:hasRole name=”admin”>

<!— 有权限—>

</shiro:hasRole>

 

 

二、Shiro授权示例程序:

1、入门的Shiro授权程序:

(1)编写shiro-permission.ini文件:

shiro-permission.ini文件里边的内容相当于在数据库查询出来的;

#用户
[users]
#用户zhangsan的密码是123,此用户具有role1和role2两个角色
zhangsan=123456,role1,role2
wangwu=123456,role2

#权限
[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
role2=user:create,items:delete
role3=user:create

权限标识符号规则:资源:操作:实例(中间使用半角:分隔)

user:create:01  表示对用户资源的01实例进行create操作。

user:create    表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。

user:*:01  表示对用户资源实例01进行所有操作。

(2)程序编写:

//shiro的授权测试:
public class AuthorizationTest {

	//角色授权、资源授权测试:
	@Test
	public void testAuthorization(){
		Factory<SecurityManager> factory = new IniSecurityManagerFactory(
				"classpath:shiro-permission.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		SecurityUtils.setSecurityManager(securityManager);
		Subject subject = SecurityUtils.getSubject();
	
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
				"123456");
		try {
			subject.login(token);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		}
		System.out.println("认证状态:" + subject.isAuthenticated());
		
		//认证通过之后执行授权:
		
		//基于角色的授权
		//hasRole传入角色标识:
		boolean ishasRole = subject.hasRole("role1");
		System.out.println("单个角色判断" + ishasRole);
		//hasAllRoles是否拥有多个角色:
		boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3"));
		System.out.println("多个角色判断" + hasAllRoles);
		// 使用check方法进行授权,如果授权不通过会抛出异常
		subject.checkRole("role2");
		
		//基于资源的授权:
		//isPermitted传入权限标识符
		boolean isPermitted = subject.isPermitted("user:create:1");
		System.out.println("单个权限判断" + isPermitted);

		boolean isPermittedAll = subject.isPermittedAll("user:create:1",
				"user:delete");
		System.out.println("多个权限判断" + isPermittedAll);
		
		// 使用check方法进行授权,如果授权不通过会抛出异常
		subject.checkPermission("items:delete:1");
	}
}

(3)执行结果:

Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权

至此,Shiro授权入门程序就完成了。在这个程序中,我们读取的是在shiro.ini配置文件中静态配置好的权限内容,但是在实际开发,我们通常是从数据库中查询用户所拥有的权限信息,因此,我们需要使用自定义的Realm进行从数据库中查询用户的权限信息。

 

2、自定义realm进行授权:

上面的程序是通过shiro-permission.ini对权限文件进行静态配置,在实际开发中,都是从数据库中获取权限数据。就需要自定义realm,由realm从数据库查询权限数据。

realm根据用户身份查询权限数据,将权限数据返回给authorizer(授权器)。

(1)自定义realm:

//自定义的Realm,需要继承AuthorizingRealm,并且重写这个类的两个方法
public class CustomRealm extends AuthorizingRealm{
	// 设置realm的名称
	@Override
	public void setName(String name) {
		super.setName("customRealm");
	}

	// 用于授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		
		//从principals获取身份信息
		//将getPrimaryPrincipal方法返回值转为真实身份(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中的身份类型)
		String userCode = (String) principals.getPrimaryPrincipal();
		
		//根据身份信息获取权限信息
		//连接数据库
		//模拟从数据库获取到数据
		List<String> permissions = new ArrayList<String>();
		permissions.add("user:create");//用户的创建
		permissions.add("items:add");//商品添加权限
		
		//查到权限数据,返回授权信息(要包括上边的permissions)
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		//将上边查询到授权信息填充到simpleAuthorizationInfo对象中
		simpleAuthorizationInfo.addStringPermissions(permissions);
		return simpleAuthorizationInfo;
	}
}

(2)编写shiro-realm.ini文件:

在shiro-realm.ini文件中配置自定义的realm,将realm设置到securityManager中。

[main]
#自定义的realm
customRealm=com.zwp.shiro.realm.CustomRealm
#将realm设置到securityManager,相当于spring中的注入
securityManager.realms=$customRealm

(3)测试:

	// 自定义realm进行资源授权测试
	@Test
	public void testAuthorizationCustomRealm() {

		Factory<SecurityManager> factory = new IniSecurityManagerFactory(
				"classpath:shiro-realm.ini");
		SecurityManager securityManager = factory.getInstance();
		SecurityUtils.setSecurityManager(securityManager);
		Subject subject = SecurityUtils.getSubject();

		// 创建token令牌
		UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
				"123456");
		// 执行认证
		try {
			subject.login(token);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		}
		System.out.println("认证状态:" + subject.isAuthenticated());
		
		// 认证通过后执行授权
		// 基于资源的授权,调用isPermitted方法会调用CustomRealm从数据库查询正确权限数据
		// isPermitted传入权限标识符,判断user:create:1是否在CustomRealm查询到权限数据之内
		boolean isPermitted = subject.isPermitted("user:create:1");
		System.out.println("单个权限判断" + isPermitted);
		boolean isPermittedAll = subject.isPermittedAll("user:create:1",
				"user:create");
		System.out.println("多个权限判断" + isPermittedAll);

		// 使用check方法进行授权,如果授权不通过会抛出异常
		subject.checkPermission("items:add:1");
	}

(4)测试结果:

Shiro框架:授权流程、授权方式、Shiro授权入门程序、自定义Realm进行授权

至此,Shiro使用自定义Realm进行授权的程序就完成了。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114710.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 史上最全 Java 多线程面试题及答案「建议收藏」

    史上最全 Java 多线程面试题及答案「建议收藏」这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题。这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也有、也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不吝指教。1、多线程有什么用? 一个可能在很多人…

  • 关于LSM树_完全m叉树

    关于LSM树_完全m叉树前言推出一个新系列,《看图轻松理解数据结构和算法》,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握。本系列包括各种堆、各种队列、各种列表、各种树、各种图、各种排序等等几十篇的样子。关于LSM树LSM树,即日志结构合并树(Log-StructuredMerge-Tree)。其实它并不属于一个具体的数据结构,它更多是一种数据结构的设计思想。大多NoSQL数据库核心思想都是基于LSM来做的,只是具体的实现不同。所以本来不打算列入该系列,但是有朋友留言了好几次让我讲LSM树,那么就说一下L

    2022年10月28日
  • centos7配置ip地址

    关于centos7获取IP地址的方法主要有两种,1:动态获取ip;2:设置静态IP地址在配置网络之前我们先要知道centos的网卡名称是什么,centos7不再使用ifconfig命令,可通过命令IPaddr查看,如图,网卡名为ens32,是没有IP地址的1、动态获取ip(前提是你的路由器已经开启了DHCP)修改网卡配置文件vi/etc/sysconfig/netwo…

  • 卷积神经网络CNN(1)——图像卷积与反卷积(后卷积,转置卷积)

    卷积神经网络CNN(1)——图像卷积与反卷积(后卷积,转置卷积)1.前言  传统的CNN网络只能给出图像的LABLE,但是在很多情况下需要对识别的物体进行分割实现endtoend,然后FCN出现了,给物体分割提供了一个非常重要的解决思路,其核心就是卷积与反卷积,所以这里就详细解释卷积与反卷积。  对于1维的卷积,公式(离散)与计算过程(连续)如下,要记住的是其中一个函数(原函数或者卷积函数)在卷积前要翻转180度图1  对…

  • PyCharm激活码永久有效PyCharm2019.3.3激活码教程-持续更新,一步到位[通俗易懂]

    PyCharm激活码永久有效PyCharm2019.3.3激活码教程-持续更新,一步到位[通俗易懂]PyCharm激活码永久有效2019.3.3激活码教程-Windows版永久激活-持续更新,Idea激活码2019.3.3成功激活

  • python求和怎么编程_python字符串数字求和

    python求和怎么编程_python字符串数字求和广告关闭腾讯云11.11云上盛惠,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!的和实现环境:python3编辑器:pycharm分析:1、阶乘的计算就是比较麻烦的一部分,用递归函数实现是比较好的方案,先定义一个递归函数实现求阶乘功能。defrecursion(n):定义递归函数实现求阶乘功能ifn==1:return1else:returnn*recurs…

    2022年10月23日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号