Springboot 集成 Shiro 和 CAS 实现单点登录(服务端篇CAS5)

f39e39c061eab760d5a337ae50ca4004.png

什么是单点登录?

先说一个需求场景,比如:一个企业的内部有N多个子系统,每个子系统都有一套自己的用户名和密码,那么企业的员工要登录N个子系统,这样一个员工 就要记住N个用户名和密码,就算各个子系统的用户名和密码都是统一的,登录每个子系统都要输入用户名和密码进行登录也是一个繁琐的操作过程,那么单点登录功能由此便应运而生了。
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

CAS架构图

这里直接说CAS整体架构是因为这不是一个入门教程,我已经默认你知道什么是SSO、什么是CAS,以及你已经装好了开发工具IDEA和Java环境Jdk1.8,并且你也知道什么是Web容器,知道Tomcat8.5+该从哪下载并启动部署,你也知道什么是Maven项目该怎么引入相关的jar包等等,所以如果你不具备以上这些知识,那么CAS服务端的学习我建议你还是先不要开始,弄清楚前面的知识点,才能畅通无阻的学习CAS服务端。
好了,这里先放架构图:

7f81fd623cb27b5bdcd2d1dc3c0c5d4d.png

现在来讲解这个架构图:
首先搭建好CAS服务端后,服务端会自定义一个数据库和用户表,用户表中存放的是用户名和密码,通过访问子系统的URL地址,如果CAS系统判定你没有登录,就会将URL重定向到CAS的服务端登录界面,用户通过输入用户数据库的用户名和密码来进行登录,待登录成功后,CAS服务端会给CAS客户端(子系统)发送登录的用户名,CAS客户端接到用户名后,会从CAS客户端的用户表中寻找对应用户名的userid,并通过该userid获取到该名用户在CAS客户端的相关权限。
我们还可以基于CAS服务端配置的用户数据库做一个用户管理界面,该界面可以对CAS服务端的用户进行一些基本的业务操作,比如新增、修改、删除等,新增用户的时候,需要同时在各个子系统的用户表中插入该用户的相关信息,然后各个子系统的管理员就可以通过子系统的角色权限设置,给该用户配置相关的角色权限了。

安装CAS服务端

讲了这么多,现在开始进入正题,我们要实现我们的目的首先要做的就是安装CAS服务端,现在网上的很多Springboot整合CAS的教程基本上都是只讲客户端的配置,看完之后云里雾里的,所以我这个教程要从CAS的服务端开始讲起,如果你们公司有人专门搭建CAS服务端,那就可以跳过本篇教程继续下一篇了。

  1. 下载Overlay
    通过阅读官网文档(https://apereo.github.io/cas/5.1.x/planning/Getting-Started.html)了解到官方建议我们:
    通过使用一个名叫Overlay的项目来生成一个可以直接用的war包,来部署服务端,于是我们先下载这个项
    目,我这里使用Maven的,下载地址:https://github.com/apereo/cas-overlay-template。

  2. 搭建Overlay项目
    将项目下好后解压缩并放入我们的工作空间,然后打开IDEA,然后选择File–Open打开我们项目所在路径,然后我们只要静静的等待Maven将项目构筑好就可以了。这时你看到的项目是这个样子的:

b32b6e42ea16a6557aa57e054112bb8d.png

这是我的项目,你的项目中并没有src目录和target目录,src目录是用户自己建立的,至于为什么后边会讲,target目录是导出war时才出现的,新导入的项目是没有的。

  1. 制成可用的CAS服务端
    现在的CAS服务端基本上是不可用的,为什么说基本上呢?因为如果你现在讲项目打成war包,并将它部署到Tomcat中去后是可以启动服务的,并且访问本地地址:http://localhost:8080/cas/login还可以看到如下界面:

b151706c834e84573b16605900c6357e.png

使用 默认账号:casuser 默认密码:Mellon还可以登录成功,不过这个CAS服务端目前并没有什么卵用,只是可以看看而已。
这两个红色警告,一个是说没有使用Https,另一个是说你只有一个静态的权限,一个写死的用户,其实就是告诉你现在的服务端是不安全的。

  • 第一个问题:关于https请求
    服务端是http的其实也可以使用,我在这个教程中不会讲解如何搭建https请求的服务端,因为我们的子项目都是http请求的,所以服务端我也不打算用https请求了,如果你想学习https请求,请参看别人的参考教程,这里不做讲解。

  • 第二个问题:关于静态用户

  1. 我们先打开项目的pom.xml文件,引入相关的jar包,注释掉用不到的jar包,我的数据库是mysql的,如果你的数据库不是,请找到对应的jar包进行引入即可:

1<?xml version="1.0" encoding="UTF-8"?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd ">
  3    <modelVersion>4.0.0</modelVersion>
  4    <groupId>org.apereo.cas</groupId>
  5    <artifactId>cas-overlay</artifactId>
  6    <packaging>war</packaging>
  7    <version>1.0</version>
  8
  9    <build>
 10        <plugins>
 11            <!--第一步:注释无用组件
 12             <plugin>
 13                <groupId>com.rimerosolutions.maven.plugins</groupId>
 14                <artifactId>wrapper-maven-plugin</artifactId>
 15                <version>0.0.4</version>
 16                <configuration>
 17                    <verifyDownload>true</verifyDownload>
 18                    <checksumAlgorithm>MD5</checksumAlgorithm>
 19                </configuration>
 20            </plugin>-->
 21            <plugin>
 22                <groupId>org.springframework.boot</groupId>
 23                <artifactId>spring-boot-maven-plugin</artifactId>
 24                <version>${springboot.version}</version>
 25                <configuration>
 26                    <mainClass>org.springframework.boot.loader.WarLauncher</mainClass>
 27                    <addResources>true</addResources>
 28                </configuration>
 29            </plugin>
 30            <plugin>
 31                <groupId>org.apache.maven.plugins</groupId>
 32                <artifactId>maven-war-plugin</artifactId>
 33                <version>2.6</version>
 34                <configuration>
 35                    <warName>cas</warName>
 36                    <failOnMissingWebXml>false</failOnMissingWebXml>
 37                    <recompressZippedFiles>false</recompressZippedFiles>
 38                    <archive>
 39                        <compress>false</compress>
 40                        <manifestFile>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MF
 41                        </manifestFile>
 42                    </archive>
 43                    <overlays>
 44                        <overlay>
 45                            <groupId>org.apereo.cas</groupId>
 46                            <artifactId>cas-server-webapp${app.server}</artifactId>
 47                        </overlay>
 48                    </overlays>
 49                </configuration>
 50            </plugin>
 51            <plugin>
 52                <groupId>org.apache.maven.plugins</groupId>
 53                <artifactId>maven-compiler-plugin</artifactId>
 54                <version>3.3</version>
 55            </plugin>
 56        </plugins>
 57        <finalName>cas</finalName>
 58    </build>
 59
 60    <dependencies>
 61        <dependency>
 62            <groupId>org.apereo.cas</groupId>
 63            <artifactId>cas-server-webapp${app.server}</artifactId>
 64            <version>${cas.version}</version>
 65            <type>war</type>
 66            <scope>runtime</scope>
 67        </dependency>
 68
 69        <!--第二步:引入数据库认证相关 start-->
 70        <dependency>
 71            <groupId>org.apereo.cas</groupId>
 72            <artifactId>cas-server-support-jdbc</artifactId>
 73            <version>${cas.version}</version>
 74        </dependency>
 75        <dependency>
 76            <groupId>org.apereo.cas</groupId>
 77            <artifactId>cas-server-support-jdbc-drivers</artifactId>
 78            <version>${cas.version}</version>
 79        </dependency>
 80        <dependency>
 81            <groupId>mysql</groupId>
 82            <artifactId>mysql-connector-java</artifactId>
 83            <version>5.1.36</version>
 84        </dependency>
 85    </dependencies>
 86
 89    <properties>
 90        <cas.version>5.1.4</cas.version>
 91        <springboot.version>1.5.3.RELEASE</springboot.version>
 92        <!-- app.server could be -jetty, -undertow, -tomcat, or blank if you plan to provide appserver -->
 93        <app.server>-tomcat</app.server>
 94        <maven.compiler.source>1.8</maven.compiler.source>
 95        <maven.compiler.target>1.8</maven.compiler.target>
 96        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 97    </properties>
 98
 99    <repositories>
100        <repository>
101            <id>sonatype-releases</id>
102            <url>http://oss.sonatype.org/content/repositories/releases/</url>
103            <snapshots>
104                <enabled>false</enabled>
105            </snapshots>
106            <releases>
107                <enabled>true</enabled>
108            </releases>
109        </repository>
110        <repository>
111            <id>sonatype-snapshots</id>
112            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
113            <snapshots>
114                <enabled>true</enabled>
115            </snapshots>
116            <releases>
117                <enabled>false</enabled>
118            </releases>
119        </repository>
120        <repository>
121            <id>shibboleth-releases</id>
122            <url>https://build.shibboleth.net/nexus/content/repositories/releases</url>
123        </repository>
124        <repository>
125            <id>spring-milestones</id>
126            <url>https://repo.spring.io/milestone</url>
127        </repository>
128    </repositories>
129
130    <!--第三步:注释掉无用的组件
131    <profiles>
132        <profile>
133            <activation>
134                <activeByDefault>false</activeByDefault>
135            </activation>
136            <id>pgp</id>
137            <build>
138                <plugins>
139                    <plugin>
140                        <groupId>com.github.s4u.plugins</groupId>
141                        <artifactId>pgpverify-maven-plugin</artifactId>
142                        <version>1.1.0</version>
143                        <executions>
144                            <execution>
145                                <goals>
146                                    <goal>check</goal>
147                                </goals>
148                            </execution>
149                        </executions>
150                        <configuration>
151                            <pgpKeyServer>hkp://pool.sks-keyservers.net</pgpKeyServer>
152                            <pgpKeysCachePath>${settings.localRepository}/pgpkeys-cache</pgpKeysCachePath>
153                            <scope>test</scope>
154                            <verifyPomFiles>true</verifyPomFiles>
155                            <failNoSignature>false</failNoSignature>
156                        </configuration>
157                    </plugin>
158                </plugins>
159            </build>
160        </profile>
161    </profiles>-->
162</project>
  1. 修改配置文件
    我们在cas-overly这个项目的根目录下新建一个src目录,并在src目录下创建一个resource目录,在resource目录下再新建一个application.properties文件,该文件中要写的就是我们的配置文件内容了:

1#STEP 3 在TOMCAT8.5中跑一个模板然后将其war包中解压出来的的application.properties复制出来,放到手动创建的src下的resources里面
  2
  3# CAS Server Context Configuration
  4server.context-path=/cas
  5server.port=9092
  6
  7#STEP 5添加认证服务
  8cas.serviceRegistry.initFromJson=true
  9
 10#STEP 4签发证书,如果是用spring boot之类嵌入式的容器,则需要改这里的配置,如果是直接部在tomcat中,则需要把tomcat改成https的
 11#server.ssl.key-store=file:/etc/cas/thekeystore
 12#server.ssl.key-store-password=changeit
 13#server.ssl.key-password=changeit
 14# server.ssl.ciphers=
 15# server.ssl.client-auth=
 16# server.ssl.enabled=
 17# server.ssl.key-alias=
 18# server.ssl.key-store-provider=
 19# server.ssl.key-store-type=
 20# server.ssl.protocol=
 21# server.ssl.trust-store=
 22# server.ssl.trust-store-password=
 23# server.ssl.trust-store-provider=
 24# server.ssl.trust-store-type=
 25
 26#server.max-http-header-size=2097152
 27#server.use-forward-headers=true
 28#server.connection-timeout=20000
 29#server.error.include-stacktrace=NEVER
 30
 31#server.tomcat.max-http-post-size=2097152
 32#server.tomcat.basedir=build/tomcat
 33#server.tomcat.accesslog.enabled=true
 34#server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
 35#server.tomcat.accesslog.suffix=.log
 36#server.tomcat.max-threads=10
 37#server.tomcat.port-header=X-Forwarded-Port
 38#server.tomcat.protocol-header=X-Forwarded-Proto
 39#server.tomcat.protocol-header-https-value=https
 40#server.tomcat.remote-ip-header=X-FORWARDED-FOR
 41#server.tomcat.uri-encoding=UTF-8
 42
 43spring.http.encoding.charset=UTF-8
 44spring.http.encoding.enabled=true
 45spring.http.encoding.force=true
 46
 47# CAS Cloud Bus Configuration
 48spring.cloud.bus.enabled=false
 49# spring.cloud.bus.refresh.enabled=true
 50# spring.cloud.bus.env.enabled=true
 51# spring.cloud.bus.destination=CasCloudBus
 52# spring.cloud.bus.ack.enabled=true
 53
 54endpoints.enabled=false
 55endpoints.sensitive=true
 56
 57endpoints.restart.enabled=false
 58endpoints.shutdown.enabled=false
 59
 60management.security.enabled=true
 61management.security.roles=ACTUATOR,ADMIN
 62management.security.sessions=if_required
 63management.context-path=/status
 64management.add-application-context-header=false
 65
 66security.basic.authorize-mode=role
 67security.basic.enabled=false
 68security.basic.path=/cas/status/**
 69
 71# CAS Web Application Session Configuration
 73server.session.timeout=300
 74server.session.cookie.http-only=true
 75server.session.tracking-modes=COOKIE
 76
 78# CAS Thymeleaf View Configuration
 80spring.thymeleaf.encoding=UTF-8
 81spring.thymeleaf.cache=false
 82spring.thymeleaf.mode=HTML
 83##
 84# CAS Log4j Configuration
 86# logging.config=file:/etc/cas/log4j2.xml
 87server.context-parameters.isLog4jAutoInitializationDisabled=true
 88
 90# CAS AspectJ Configuration
 92spring.aop.auto=true
 93spring.aop.proxy-target-class=true
 94
 96# CAS Authentication Credentials
 98#STEP4 注释掉写死的用户 改用jdbc的用户 START
 99#cas.authn.accept.users=casuser::Mellon
100
101cas.authn.jdbc.query[0].sql=select * from s_user where username=?
102cas.authn.jdbc.query[0].healthQuery=
103cas.authn.jdbc.query[0].isolateInternalQueries=false
104cas.authn.jdbc.query[0].url=jdbc:mysql://172.18.18.25:3306/pa_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
105cas.authn.jdbc.query[0].failFast=true
106cas.authn.jdbc.query[0].isolationLevelName=ISOLATION_READ_COMMITTED
107cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
108cas.authn.jdbc.query[0].leakThreshold=10
109cas.authn.jdbc.query[0].propagationBehaviorName=PROPAGATION_REQUIRED
110cas.authn.jdbc.query[0].batchSize=1
111cas.authn.jdbc.query[0].user=root
112#cas.authn.jdbc.query[0].ddlAuto=create-drop
113cas.authn.jdbc.query[0].maxAgeDays=180
114cas.authn.jdbc.query[0].password=dhcc
115cas.authn.jdbc.query[0].autocommit=false
116cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
117cas.authn.jdbc.query[0].idleTimeout=5000
118# cas.authn.jdbc.query[0].credentialCriteria=
119# cas.authn.jdbc.query[0].name=
120# cas.authn.jdbc.query[0].order=0
121# cas.authn.jdbc.query[0].dataSourceName=
122# cas.authn.jdbc.query[0].dataSourceProxy=false
123cas.authn.jdbc.query[0].fieldPassword=password
124
125# cas.authn.jdbc.query[0].fieldExpired=
126# cas.authn.jdbc.query[0].fieldDisabled=
127# cas.authn.jdbc.query[0].principalAttributeList=sn,cn:commonName,givenName
128
129#cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
130#cas.authn.jdbc.query[0].passwordEncoder.type=com.example.CustomPasswordEncoder
131#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
132#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
133
134#cas.authn.jdbc.query[0].passwordEncoder.secret=
135#cas.authn.jdbc.query[0].passwordEncoder.strength=16
136
137# cas.authn.jdbc.query[0].principalTransformation.suffix=
138# cas.authn.jdbc.query[0].principalTransformation.caseConversion=NONE|UPPERCASE|LOWERCASE
139# cas.authn.jdbc.query[0].principalTransformation.prefix=
140# STEP4 END
141
142
144# CAS Delegated Authentication
146#cas.authn.pac4j.bitbucket.clientName=Bitbucket
147#cas.authn.pac4j.dropbox.clientName=Dropbox
148#cas.authn.pac4j.facebook.clientName=Facebook
149#cas.authn.pac4j.foursquare.clientName=Foursquare
150#cas.authn.pac4j.github.clientName=Github
151#cas.authn.pac4j.google.clientName=Google
152#cas.authn.pac4j.linkedIn.clientName=LinkedIn
153#cas.authn.pac4j.paypal.clientName=PayPal
154#cas.authn.pac4j.twitter.clientName=Twitter
155#cas.authn.pac4j.yahoo.clientName=Yahoo
156#cas.authn.pac4j.windowsLive.clientName=Windows Live
157#cas.authn.pac4j.wordpress.clientName=WordPress
158
159#多属性
160cas.authn.attributeRepository.jdbc[0].singleRow=true
161cas.authn.attributeRepository.jdbc[0].order=0
162cas.authn.attributeRepository.jdbc[0].url=jdbc:mysql://172.18.18.25:3306/pa_db?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
163cas.authn.attributeRepository.jdbc[0].username=username
164cas.authn.attributeRepository.jdbc[0].user=root
165cas.authn.attributeRepository.jdbc[0].password=dhcc
166cas.authn.attributeRepository.jdbc[0].sql=select * from s_user where {0}
167cas.authn.attributeRepository.jdbc[0].dialect=org.hibernate.dialect.MySQLDialect
168cas.authn.attributeRepository.jdbc[0].ddlAuto=none
169cas.authn.attributeRepository.jdbc[0].driverClass=com.mysql.jdbc.Driver
170cas.authn.attributeRepository.jdbc[0].leakThreshold=10
171cas.authn.attributeRepository.jdbc[0].propagationBehaviorName=PROPAGATION_REQUIRED
172cas.authn.attributeRepository.jdbc[0].batchSize=1
173cas.authn.attributeRepository.jdbc[0].healthQuery=SELECT 1
174cas.authn.attributeRepository.jdbc[0].failFast=trueyeshi
175#http访问
176cas.tgc.secure=false

看上面的配置文件你会发现我配置了mysql的jdbc连接请求,其实就是为了给CAS服务端配置用户名和密码验证的,你自己做的话,需要在你的数据库中创建一个数据库空间和一张用户表,并且保证该表中最少有三个字段:id,username和password,这个配置文件中写的是我的测试服务器的配置,你要改成自己的哦。
这里有几个点要注意下:
cas.authn.accept.users=casuser::Mellon这个配置记得删掉,这就是那个写死的用户
cas.authn.jdbc.query[0]这些配置就是数据库验证相关的内容
在cas.authn.jdbc.query[0].sql中,程序会把你登录时输入的用户名作为参数传进去
cas.authn.jdbc.query[0].fieldPassword则是指明那一列对应的是你输入的密码,目前没有做MD5
如果使用http访问 必须加入 cas.tgc.secure=false 否则登录状态不能共享。

  1. 加入http访问服务

请在系统的C:\WINDOWS\System32\drivers\etc\hosts 文件中加入:
127.0.0.1 com.dhcc.cas
这么做的目的是将这个IP地址指向这个域名,其实本意是为了https访问做的工作,如果想知道其目的可以查看cas https访问相关的资料,本教程里就不再细说了。

这里可能不好理解,我先来讲一个我遇到的问题,你就可以理解了:
配置好CAS的客户端后,我就开始测试我的客户端子系统,在浏览器中输入我的子系统项目地址:
http://com.dhcc.cas:9093
后由于我的子系统的配置,访问界面会重定向到
http://com.dhcc.cas:9092/cas/login?service:http://com.dhcc.cas:9093/
但是这个界面理论上来说应该是跳转到CAS服务端的登录界面的,可是我的这个路径却无法跳转,
并展示如下界面:

b4e3223ed46983d1f07decc3a9266c48.png

我百思不得其解,尝试了各种方法也不行,直到我发现了将路径改为:
http://com.dhcc.cas:9092/cas/login?service=https://com.dhcc.cas:9093/
界面会自动跳转到CAS服务端的登录界面,这时我才开始回忆起CAS服务端是不是哪里我没有配置对,于是我在网上查资料才知道CAS4.2以上光加入cas.tgc.secure=false 这个参数配置是不够的,还要对HTTPSandIMAPS-10000001.json这个文件中进行修改,大家可能会问了,我怎么没看到这个文件?
因为默认的项目架构是没有这个文件的,我们要将导出的war包解压,然后在WEB-INF\classes\services这个路径下找到这个文件,然后在我们的项目中的resources目录下再新建一个services目录,并将该文件拷贝到这个路径下即可。
现在你的项目架构应该是这个样子的:

e95a1c0f0639a887ef96844d99f0f3bc.png

引入这个文件肯定是为了修改它,我们可以看到这个json中有行代码,其实是个正则表达式:

1"serviceId" : "^(https|imaps)://.*"

了解json的都知道,这里其实是说serviceId的值是所有带https和imaps的url请求都会被当成已经注册的服务,我们只要将它改成下面这样就可以了:

1"serviceId" : "^(https|imaps|http)://.*"

这样我们就可以安心的使用CAS的http请求服务了。

结语

至此,我们的CAS服务端基本上就搭建好了,只要将它打成war包,并放到tomcat中启动起来,便可以作为们的单点登录的服务端使用了。
这里需要注意一下几点:

  1. 注意自定义的配置文件是否写对了,尤其是数据库的配置。

  2. 一定要加入并修改HTTPSandIMAPS-10000001.json文件,否则后期你的CAS客户端肯定不会自动跳转到登录界面。

只要你的服务端可以正常启用,你就成功了一半了,下一篇我们就开始讲解CAS客户端的配置了。

1source: //jasoncool.github.io/2017/11/29/Springboot集成Shiro和Cas实现单点登录-服务端篇CAS5

eacb09ac3cc8f2278d53c7f30edd656b.png

喜欢,在看

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot是一个用于快速开发Java应用程序的开源框架,Shiro是一个强大且易于使用的Java安全框架,Redis是一个开源的内存数据库。结合使用这些技术可以实现单点登录功能。 在Spring Boot中使用Shiro来处理认证和授权,可以通过配置Shiro的Realm来实现用户的登录认证和权限控制。将用户的信息存储在Redis中,利用Redis的持久化特性来实现用户登录状态的共享和存储。 首先,在Spring Boot项目的配置文件中配置Redis的连接信息,以便连接到Redis数据库。 然后,创建一个自定义的Shiro的Realm,在其中重写认证和授权的方法。在认证方法中,将用户的登录信息存储到Redis中,以便其他服务可以进行验证。在授权方法中,根据用户的角色和权限进行相应的授权操作。 接着,在Spring Boot项目的配置类中配置Shiro的相关设置,包括Realm、Session管理器、Cookie管理器等。 最后,可以在Controller层中使用Shiro的注解来标记需要进行认证和授权的接口,以确保只有登录后且具备相应权限的用户才能访问这些接口。 总的来说,通过使用Spring BootShiro和Redis的组合,可以实现单点登录的功能。用户在登录后,将登录信息存储到Redis中,其他服务可以通过验证Redis中的数据来判断用户的登录状态。同时,Shiro提供了强大的认证和授权功能,可以确保只有具备相应权限的用户才能访问受保护的接口。这些功能的具体实现可以通过深入研究Spring BootShiro和Redis的源码来了解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值