文章目录

  • ​​1 环境搭建​​
  • ​​项目结构​​
  • ​​添加依赖​​
  • ​​添加 yml 配置​​
  • ​​2 数据库表​​
  • ​​3 项目代码​​
  • ​​Entity​​
  • ​​Mapper​​
  • ​​Service​​
  • ​​自定义的 Relam​​
  • ​​配置类 Config​​
  • ​​Controller​​
  • ​​自定义异常​​
  • ​​前端测试页​​
  • ​​4 测试​​
  • ​​测试:登录功能​​
  • ​​测试:RememberMe 功能​​
  • ​​测试:登出功能​​
  • ​​测试:角色、权限功能​​
  • ​​测试:ehcache缓存​​
  • ​​5 知识点​​
  • ​​常用注解​​
  • ​​会话管理 SessionManager​​

1 环境搭建

项目结构

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java

添加依赖

<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.9.0</version>
</dependency>

<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--配置Thymeleaf与Shrio的整合依赖-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>

<!--Shiro整合EhCache-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

</dependencies>

添加 yml 配置

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_02

2 数据库表

role 表

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_03

role_user 表

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_04


user 表

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_05

3 项目代码

Entity

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_06

Mapper

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_07

Service

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_08


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_09

自定义的 Relam

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_10


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_11

配置类 Config

设置 SecurityManager,并装入自定义的 Realm、rememberMe、缓存管理器

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_12


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_13


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_14


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_15

缓存管理器的参数配置在了 xml 中

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_16

补充:配置多 Realm

配置多 Realm,首先要实现多个 Realm,在配置类中将这些 Realm 注入,并在 SecurityManager 中指定策略、装入这些 Realm 的集合即可

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_17


当应用程序配置多个 Realm 时,例如:用户名密码校验、手机号验证码校验等等。

Shiro 的 ModularRealmAuthenticator 会使用内部的 AuthenticationStrategy 组件判断认证是成功还是失败。AuthenticationStrategy 是一个无状态的组件,它在身份验证尝试中被询问 4 次(这4 次交互所需的任何必要的状态将被作为方法参数):

(1)在所有 Realm 被调用之前

(2)在调用 Realm 的 getAuthenticationInfo 方法之前

(3)在调用 Realm 的 getAuthenticationInfo 方法之后

(4)在所有 Realm 被调用之后

认证策略的另外一项工作就是聚合所有 Realm 的结果信息封装至一个

AuthenticationInfo 实例中,并将此信息返回,以此作为 Subject 的身份信息。

Shiro 中定义了 3 种认证策略的实现,ModularRealmAuthenticator 内置的认证策略默认实现是AtLeastOneSuccessfulStrategy 方式。可以通过配置修改策略

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_18

Controller

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_19


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_20


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_21

自定义异常

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_22

前端测试页

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_23


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_24

4 测试

测试:登录功能

输入完信息后,点击登录

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_25

可以看到后端已经来到对应接口

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_26

先是来到了我们的登录认证方法 doGetAuthenticationInfo

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_缓存_27

之后来到了我们自定义的 Realm 的授权方法 doGetAuthorizationInfo

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_28

并在授权方法这里获取角色、权限

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_29

成功来到了首页

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_30

测试:RememberMe 功能

若登录时没有勾选记住我,那么后台也不会走 RememberMe 的逻辑,不会存入 Cookies 中用户信息,我们访问一个需要认证登录的页面,则直接跳转到登录页面

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_31


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_32

另外如果我们不勾选记住我,那么自然也不会有对应的 Cookies

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_33

我们试着勾选记住我

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_34

测试:登出功能

点击登出后,对应的 Cookies 也被清除了

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_35

测试:角色、权限功能

前端页面使用 shiro-thymeleaf 模板,进行角色或权限的个性化功能展示

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_36

后台也要做好校验,直接用注解即可

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_37

加入 李四 登录,在之前数据表中我们的测试数据是李四没有这些权限,并且是用户角色,因此前端不会显示,后台接口之间访问也会阻止

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_38

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_spring boot_39

而张三我们的数据中设定的是他有这两种权限以及admin管理员角色,下面测试便可以展示

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_40


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_41

测试:ehcache缓存

在 ShiroConfig 中先注释掉缓存管理器

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_会话管理_42


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_43


【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_java_44


我们走一条有角色校验的请求,多走几次发现,每走一次后台都会打印 dao 层的日志,可见每次都需要去数据库查一次

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_45

接下来我们把之前的注释去掉,开启缓存管理器,我们还是访问上面的请求,发现并不会再查一次数据库,那么缓存便配置成功了

【SpringBoot+Shiro 用户认证授权权限项目总结】环境搭建、数据库、项目代码、功能测试截图_mybatis_46

5 知识点

常用注解

(1)@RequiresAuthentication
验证用户是否登录,等同于方法subject.isAuthenticated()

(2)@RequiresUser
验证用户是否被记忆:
登录认证成功subject.isAuthenticated()为true
登录后被记忆subject.isRemembered()为true

(3)@RequiresGuest
验证是否是一个guest的请求,是否是游客的请求
此时subject.getPrincipal()为null

(4)@RequiresRoles
验证subject是否有相应角色,有角色访问方法,没有则会抛出异常
AuthorizationException。
例如:@RequiresRoles(“aRoleName”)
void someMethod();
只有subject有aRoleName角色才能访问方法someMethod()

(5)@RequiresPermissions
验证subject是否有相应权限,有权限访问方法,没有则会抛出异常
AuthorizationException。
例如:@RequiresPermissions (“file:read”,”wite:aFile.txt”)
void someMethod();
subject必须同时含有file:read和wite:aFile.txt权限才能访问方法someMethod()

会话管理 SessionManager

会话管理器,负责创建和管理用户的会话(Session)生命周期,它能够在任何环境中在本地管理用户会话,即使没有Web/Servlet/EJB容器,也一样可以保存会话。默认情况下,Shiro会检测当前环境中现有的会话机制(比如Servlet容器)进行适配,如果没有(比如独立应用程序或者非Web环境),它将会使用内置的企业会话管理器来提供相应的会话管理服务,其中还涉及一个名为SessionDAO的对象。SessionDAO负责Session的持久化操作(CRUD),允许Session数据写入到后端持久化数据库

SessionManager由SecurityManager管理。Shiro提供了三种实现

(1) DefaultSessionManager:用于JavaSE环境

(2) ServletContainerSessionManager:用于web环境,直接使用Servlet容器的会话

(3) DefaultWebSessionManager:用于web环境,自己维护会话(不使用Servlet容器的
会话管理)

编码
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute(“key”,”value”)

说明

  • Controller 中的 request,在 shiro 过滤器中的 doFilerInternal 方法,被包装成
    ShiroHttpServletRequest。
  • SecurityManager 和 SessionManager 会话管理器决定 session 来源于 ServletRequest还是由 Shiro 管理的会话。
  • 无论是通过 request.getSession 或 subject.getSession 获取到 session,操作
    session,两者都是等价的。