Spring Boot与Shiro实现权限管理01

1. Shiro框架简介

Shiro是一个易于使用,功能强大的开源安全框架,Shiro提供了简洁直观的API来支撑应用程序的安全基石,主要包含以下四个部分:

  • 1.身份认证(Authentication)
  • 2.授权(Authorization)
  • 3.会话管理(Session Management)
  • 4.加密(Cryptography)

Shiro最主要最核心的功能主要包含上述四个部分,同时也提供了其余的支持性功能,就不一一介绍了。

1.1 Shiro主要的概念

认证(Authentication)
认证就是验证用户身份的过程,在用户访问系统时,通过比对用户提供的身份信息与存储在系统中数据库的身份信息比对,确定用户是其“本人”。

授权(Authorization)
授权,也就是访问控制,是通过检查用户的角色和权限确定用户是否被允许做某个操作的过程。

凭证(Credential)
凭证是用来核实用户身份的一类信息,凭证与用户信息一起提交,应用程序对用户提交的凭证进行验证以确定是相关用户。凭证通常是非常秘密的东西,只有特定的用户才会知道,一般为密码,密钥以及一些生物识别数据,如指纹等。

权限(Permission)
权限是一个描述应用程序中原始功能的声明,权限是安全策略中最底层的结构,它们只定义了应用程序可以做“什么”,而不描述“谁”能够执行这些操作,权限只是一个行为声明。

用户标识(Principal)
Principal 是被应用程序用来识别用户身份的任何具有唯一性的属性,用户标识可以是任何对系统而言“有意义”的东西,如用户名、手机号、用户 ID 等。

领域(Realm)
Realm 是用户身份信息,权限,角色信息的提供者。Realm 从系统数据源中获取数据,转交给 Shiro 以进行身份认证和权限管理,在开发中一般不会直接实现 Realm 接口,而是基于其子类 AuthenticatingRealm 或 AuthorizingRealm 进行扩展。

主题(Subject)
Subject 只是一个安全术语,一般表示系统用户的一个特定安全 “视图”,基本上它是任何实体的代表,这些实体会与应用程序一起做一些事情。

角色(Role)
角色是一个抽象的概念,可以看成是一组权限的集合,如果一个用户的角色是 A,那就意味着他拥有角色 A 涵盖的所有权限。

会话(Session)
会话是一个有状态的数据上下文,它与在一段时间内和应用程序交互的单个用户相关联。当用户登陆系统时,会话被创建,我们可以将数据保存到会话中,并在需要时从会话中读取这些数据,当用户主动登出系统或由于长时间不与系统交互而导致超时被动登出系统时,会话数据将被销毁。

1.2 Shiro主要工作流程

在这里插入图片描述

Subject

Subject 实例都强制绑定到 SecurityManager 上,当我们调用 Subject 的方法时,具体的操作最终都会转交给相关的 SecurityManager 进行处理。

SecurityManager

SecurityManager 是 Shiro 体系结构的核心,它协调着内部的其它安全组件,这些安全组件一起形成一种互相协作支持的关系,共同完成 Shiro 提供的所有功能。使用时只需要应用程序配置了 SecurityManager,通常就不需要再理会它,我们只需要和 Subject 的 API 进行交互就可以了。

Realm

Realm 是 Shiro 与应用程序数据之间交换的“桥梁”,当 Shiro 真正需要与安全性相关的数据(例如用户帐户,用户角色,权限等)进行交互以执行身份验证和授权时,Shiro 会从一个或多个为应用程序配置的 Realm 中查找这些数据。

可以简单地把 Realm 理解为特定于安全性的 DAO,它封装了对安全性相关数据的访问,在配置 Shiro 时,我们必须至少指定一个 Realm 以用于身份验证(或授权)。

身份认证器(Authenticator)和访问控制器(Authorizer)

身份认证器(Authenticator)是负责执行和响应用户认证(登录)的组件。当用户尝试登录时,该逻辑由 Authenticator 执行,Authenticator 知道如何与一个或多个 Realm 进行协调,从这些 Realm 中获取用户的身份信息,然后完成身份认证过程。

访问控制器(Authorizer)是负责决定用户对应用中具体资源能否访问和操作的组件,是最终决定用户是否被允许做某事的机制,与 Authenticator 一样,Authorizer 也知道如何与多个 Realm 协调,以获取角色和权限信息,Authorizer 使用这些信息来确定用户是否被允许执行某个动作。

2.Shiro身份认证

身份认证指的是认证系统用户身份的过程,其目的是为了控制系统只为可信用户提供服务,避免受到非法用户的损害,用户只有提供了系统信任的“凭据”,才能顺利通过身份认证,访问系统中的资源。Shiro Authentication 的设计目的在于让身份认证过程直接,清晰和易扩展。

身份认证一般分为三步:

  • 获取用户提供的身份标识(principals),比如用户名,手机号码等,另一个是获取用户提供的身份凭证(credentials)。
  • 将身份标识和身份凭证提交到系统。
  • 成功提交到系统后,系统会根据身份标识获取到系统中保存的用户身份信息,将两者进行比对,如果用户提交的凭证匹配,那么就认为登录者是用户“本人”。

2.1 具体实现

创建Spring Boot项目,添加相关依赖。
pom.xml

       <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.1</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

Shiro 支持从系统初始化文件(.ini)中解析用户身份和权限信息,我们将使用 .ini 文件模拟系统中保存真实用户信息的数据源,这里首先需要在 main 文件夹下新建一个 resources 文件夹,然后在 resources 文件夹下创建 shiro.ini 文件。

[users]
root = 123
guest = 123

这里表示系统中存在两个用户,其用户名分别为 root 和 guest,root 用户的密码为 123,guest 用户的密码为 123。

基本的环境配置已经完成了,接下来就可以完成身份认证的demo了。

  • 1.首先需要将 shiro.ini 文件配置到 SecurityManager 中,同时 SecurityManager 会负责对一些相关组件进行初始化。
        IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
  • 2.将用户身份信息保存到 UsernamePasswordToken。
        // 获取当前用户
        Subject subject = SecurityUtils.getSubject();
        if(!subject.isAuthenticated()){
            // 使用用户名和密码登陆
            UsernamePasswordToken token = new UsernamePasswordToken("root", "123");
            token.setRememberMe(true);

            // 身份认证
            try{
                subject.login(token);
                System.out.println("登陆成功");
            }catch(UnknownAccountException e){
                System.out.println("用户名为:" + token.getPrincipal() + " 的用户不存在");
            }catch (IncorrectCredentialsException e){
                System.out.println("密码错误");
            }catch (LockedAccountException e){
                System.out.println("用户已被冻结");
            }catch (AuthenticationException e){
                System.out.println("未知错误:" + e);
            }

当login方法被调用时,SecurityManager 将接收 AuthenticationToken(这里为 token ),然后交给 Authenticator,之后 Authenticator 再将其调度到对应的 Realm 上,让 Realm 根据需要执行身份验证检查。如果登录尝试失败,那么可以通过运行时异常 AuthenticationException 来捕获到具体的出错原因。

测试效果:
使用root,123测试效果。
在这里插入图片描述
使用user,123测试效果,此时这个用户不存在。
在这里插入图片描述
其余的情况这里就不一一演示了。

3. Shiro授权

授权,也叫访问控制,是确定用户对系统中资源能否访问并进行操作的过程。授权一般用来保护系统资源,避免资源被错误的访问和修改,比如敏感数据泄露,关键数据被修改等。

3.1 基于角色的授权

在应用程序中进行安全检查时可以基于用户角色进行检查,通过检查用户是否拥有某一角色而确定其是否能够执行具体操作。

在shiro.ini 文件中添加roles信息。

[users]
root = 123, admin
guest = 123, writer, reader

[roles]
admin = *
writer = book:write
reader = lib:view:java-in-action

这里表示guest用户拥有writer角色,reader角色,,writer 拥有 “book:write”(写书)的权限,reader 拥有 “lib:view:java-in-action” 的权限。

基于角色的权限检查


        // 基于角色的权限检查
        if(subject.hasRole("writer")){
            System.out.println("拥有writer角色");
        }else{
            System.out.println("没有writer角色");
        }

测试效果:
使用guest,123测试效果。
在这里插入图片描述

3.2 基于权限的授权

执行访问控制的更好方法通常是基于权限的授权,因为这样能够做到更小粒度的控制,同时降低了代码实现的复杂度。Subject 提供了多个 isPermitted*(args) 方法来进行权限检查,isPermitted* 方法主要接受两类参数,一类是字符串,另一类是 Permission 接口。

通过实现 Permission 接口来承载权限信息
Permission 接口提供了对权限表述进行检查的能力,能够确保系统中使用的权限符合你对权限定义的一些限制。

通过字符串承载权限信息
通过字符串表述权限实际上使用的是通配符权限(WildcardPermission),它是 Permission 的一个具体实现,提供了极大的灵活性。例如:

  • “printer:query”:字符串分成两个部分,第一部分表示操作者(printer),第二部分表示允许执行的操作(query)。
  • “printer:print,query”:一个操作者有执行多个操作权限的方式,第一部分表示操作者(printer),第二部分表示允许执行的操作(query 和 print)。
  • "printer: * ":* 表示所有,即操作者(printer)拥有所有操作权限。
  • “printer:print:epsoncolor”:具体到实例的方式,表示操作者(printer)能够执行(print)操作,另外对操作的对象(epsoncolor)也进行了定义。

基于权限(对具体资源的操作权限)的权限检查

        // 基于权限的检查,检查是否有写的权限
        if(subject.isPermitted("book:write")){
            System.out.println("拥有写权限");
        }else{
            System.out.println("没有写权限");
        }

        // 基于权限的检查,检查对具体实例的操作权限
        if(subject.isPermitted("lib:view:java-in-action")){
            System.out.println("拥有权限读 java-in-action");
        }else{
            System.out.println("没有权限读 java-in-action");
        }

测试效果:
使用guest,123测试效果。
在这里插入图片描述

4. Shiro会话管理

        // 获取会话对象
        Session session = subject.getSession();

        // 会话管理
        session.setAttribute("username", "guest");
        System.out.println("当前登陆用户" + session.getAttribute("username"));

测试效果:
使用guest,123测试效果。
在这里插入图片描述
基础的Shiro的使用就结束了,接着就是使用Spring Boot框架集成Shiro框架实现一个简单的项目demo。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

picacho_pkq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值