Shiro 自定义realm授权与认证的实现

2024-08-21 15:32

本文主要是介绍Shiro 自定义realm授权与认证的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

……List……

1.项目需求

2.shiro核心组件

3.自定义realm认证

4.自定义realm授权

5.思考总结


……1.项目需求……


          企业项目中少不了权限管理,总的来说,权限管理就是用户认证与用户授权。用户拥有了权限即可操作权限范围内的资源,系统不知道主体是否具有访问权限需要对用户的访问进行控制。shiro是一套优秀的权限管理框架。来了解一下shiro的授权和认证。




……2.shiro核心组件……




关于shiro权限管理(授权和认证)离不开上面三个核心组件:subject,securitymanager,realm。


Subject:即“当前操作用户”,在Shiro中主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。 

SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。 

Realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。在realm中存储授权和认证的逻辑。所以realm很重要。从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。 


明白了上面三个基本组件,在分析一下实现的流程:


……3.自定义realm认证……




1、通过ini配置文件创建securityManager

2、调用subject.login方法主体提交认证,提交的token

3、securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。

4、ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息

5、IniRealm根据输入的token(UsernamePasswordToken)从 shiro-first.ini查询用户信息,根据账号查询用户信息(账号和密码)
如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)
如果查询不到,就给ModularRealmAuthenticator返回null

6、ModularRealmAuthenticator接收IniRealm返回Authentication认证信息
  如果返回的认证信息是null,ModularRealmAuthenticator抛出异常(org.apache.shiro.authc.UnknownAccountException)
         如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常(org.apache.shiro.authc.IncorrectCredentialsException)


// 自定义realm@Testpublic void testCustomRealm() {// 创建securityManager工厂,通过ini配置文件创建securityManager工厂Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");// 创建SecurityManagerSecurityManager securityManager = factory.getInstance();// 将securityManager设置当前的运行环境中SecurityUtils.setSecurityManager(securityManager);// 从SecurityUtils里边创建一个subjectSubject subject = SecurityUtils.getSubject();// 在认证提交前准备token(令牌)// 这里的账号和密码 将来是由用户输入进去UsernamePasswordToken token = new UsernamePasswordToken("zhouzhou","123");try {// 执行认证提交subject.login(token);} catch (AuthenticationException e) {e.printStackTrace();}// 是否认证通过boolean isAuthenticated = subject.isAuthenticated();System.out.println("subject.login(token);之后,是否认证通过:" + isAuthenticated);// 退出操作subject.logout();// 是否认证通过isAuthenticated = subject.isAuthenticated();System.out.println("2.subject.logout();之后是否认证通过:" + isAuthenticated);}


shiro-realm.ini:

[main]
#自定义 realm
customRealm=cn.itcast.shiro.realm.CustomRealm
#将realm设置到securitymanager,相当于spring注入 
securityManager.realms=$customRealm


CumtomRealm.java (自定义类)

package cn.itcast.shiro.realm;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;public class CustomRealm extends AuthorizingRealm {// 设置realm的名称@Overridepublic void setName(String name) {super.setName("customRealm");}// 用于认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// token是用户输入的// 第一步从token中取出身份信息String userCode = (String) token.getPrincipal();// 第二步:根据用户输入的userCode从数据库查询// ....// 模拟从数据库查询到密码String password = "123";// 如果查询到返回认证信息AuthenticationInfoSimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password, this.getName());return simpleAuthenticationInfo;}// 用于授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stubreturn null;}}

console:



          真正运用到项目中,需要将数据库获取的用户身份信息存入token,subject.isAuthenticated()用这个方法来判断是否通过了认证。


……4.自定义realm授权……




授权与认证类似,是在ini文件里面定义一套授权规则,在环境中去加载。


1、 执行subject.isPermitted("user:create")

2、 securityManager通过ModularRealmAuthorizer进行授权

3、 ModularRealmAuthorizer调用realm获取权限信息

4、 ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配

// 自定义realm进行资源授权测试@Testpublic void testAuthorizationCustomRealm() {// 创建SecurityManager工厂Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");// 创建SecurityManagerSecurityManager securityManager = factory.getInstance();// 将SecurityManager设置到系统运行环境,和spring后将SecurityManager配置spring容器中,一般单例管理SecurityUtils.setSecurityManager(securityManager);// 创建subjectSubject subject = SecurityUtils.getSubject();// 创建token令牌UsernamePasswordToken token = new UsernamePasswordToken("zhouzhou","123");// 执行认证try {subject.login(token);} catch (AuthenticationException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println("认证状态:" + subject.isAuthenticated());
//		认证状态:true// 认证通过后执行授权// 基于资源的授权,调用isPermitted方法会调用CustomRealm从数据库查询正确权限数据// isPermitted传入权限标识符,判断user:create:1是否在CustomRealm查询到权限数据之内boolean isPermitted = subject.isPermitted("user:create:1");System.out.println("单个权限判断" + isPermitted);
//		单个权限判断trueboolean isPermittedAll = subject.isPermittedAll("user:create:1","user:create");System.out.println("多个权限判断" + isPermittedAll);
//		多个权限判断true// 使用check方法进行授权,如果授权不通过会抛出异常subject.checkPermission("items:add:1");}



shiro-realm.ini:

[main]
#自定义 realm
customRealm=cn.itcast.shiro.realm.CustomRealm
#将realm设置到securitymanager,相当于spring注入 
securityManager.realms=$customRealm



自定义:customRealm.java


package cn.itcast.shiro.realm;import java.util.ArrayList;
import java.util.List;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;public class CustomRealm extends AuthorizingRealm {// 设置realm的名称@Overridepublic void setName(String name) {super.setName("customRealm");}// 用于认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// token是用户输入的// 第一步从token中取出身份信息String userCode = (String) token.getPrincipal();// 第二步:根据用户输入的userCode从数据库查询// ....// 模拟从数据库查询到密码String password = "123";// 如果查询到返回认证信息AuthenticationInfoSimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, password, this.getName());return simpleAuthenticationInfo;}// 用于授权@Overrideprotected 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;}}




console:




……5.思考总结……

      

       Authorization 授权

      Authentication 认证

      (要分清楚这两个单词…)


      权限管理分为粗粒度和细粒度,细粒度在数据级别没有共同语言,需要写到业务逻辑中。粗粒度权限管理比较容易将权限管理的代码抽取出来在系统架构级别统一处理。节省开发时间,提高开发效率。

      多学习,多思考。




这篇关于Shiro 自定义realm授权与认证的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093552

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringBatch数据写入实现

《SpringBatch数据写入实现》SpringBatch通过ItemWriter接口及其丰富的实现,提供了强大的数据写入能力,本文主要介绍了SpringBatch数据写入实现,具有一定的参考价值,... 目录python引言一、ItemWriter核心概念二、数据库写入实现三、文件写入实现四、多目标写入

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件