基于SpringbootShiro实现的CAS单点登录

概述

单点登录(Single Sign On,SSO)是一种登录管理机制,主要用于多系统集成,即在多个系统中,用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无须多次登录。常见的例子就是,当我们在淘宝网上登录了之后,如果再访问天猫网的话是不需要再次登录的。

详细

一、运行效果

image.png

image.png

二、实现过程

①、cas单点登录流程图

CAS是SSO的一种实现方式,CAS系统分为服务端与客户端,服务端提供登录认证的功能,客户端需要跳转到服务端进行登录认证,大体流程如下

image.png

②、cas 服务端搭建

CAS 服务端登录需要使用https,在本地我们可以使用 JDK 自带的 keytool 工具生成数字证书,具体流程和配置如下:

a 修改hosts文件,将要配置的CAS服务端域名映射到本地:

127.0.0.1       www.xiaoti.com

b 生成密钥库文件,这里设置密钥库口令,名字与姓氏处填写单点登录服务器的域名(这里是 www.xiaoti.com),其余项可随便填写。654321,设置密钥口令:654321,两者须相同:

c 查看生成的密钥库,输入密钥库密码654321:keytool -list -keystore localhost.keystored 生成crt证书文件,输入密钥库密码654321:keytool -export -alias localhost -keystore localhost.keystore -file localhost.crte 客户端信任证书,这里需要输入的密码是changeit:keytool -import -keystore "D:\Program Files\Java\jdk1.8.0_66\jre\lib\security\cacerts" -file localhost.crt -alias localhostf tomcat配置,server.xml配置:<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"maxThreads="200"SSLEnabled="true"scheme="https"secure="true"clientAuth="false"sslProtocol="TLS"keystoreFile="D:\dev\localhost.keystore"keystorePass="654321" />

 

③、 新建cas服务端项目

CAS已经提供了服务端的基本war包实现,我们只需在其基础上作修改即可,使用maven 的oerlay配置可以通过覆盖的方式来进行修改。

a 新建Maven webapp项目,这里命名为cas-server-demo,引入依赖:

<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>gdou.laixiaoming</groupId><artifactId>cas-server-demo</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>cas-server-demo Maven Webapp</name><url>http://maven.apache.org</url><properties><cas.version>5.2.5</cas.version></properties><dependencies><dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-webapp</artifactId><version>${cas.version}</version><type>war</type><scope>runtime</scope></dependency></dependencies><build><finalName>cas</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><configuration><failOnMissingWebXml>false</failOnMissingWebXml><warName>cas</warName><overlays><overlay><groupId>org.apereo.cas</groupId><artifactId>cas-server-webapp</artifactId></overlay></overlays></configuration></plugin></plugins></build></project>

b 打包,选择上面我们配置的tomcat,启动:
浏览器打开https://www.xiaoti.com:8443/cas/login,默认登录名和密码是casuserMellon,输入后可成功登录

④、配置数据库认证

上面我们成功搭建了CAS Server,但是只能使用默认的用户名和密码进行登录,如果我们的用户名和密码是存储在数据库的话,需要引入 JDBC的支持并进行配置:

a 首先,pom.xml配置文件中增加依赖:

<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-support-jdbc</artifactId><version>${cas.version}</version></dependency><dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-support-jdbc-drivers</artifactId><version>${cas.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.36</version></dependency>

b 创建用户密码表:

CREATE TABLE `user` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `userName` varchar(15) DEFAULT NULL,

  `password` char(32) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

c 将war包中的的application.properties复制出来:

image.png

放到项目如下位置,这里的路径需要对应(确保部署后的application.properties可以对原文件进行覆盖),才能实现更新:

image.png

d 修改application.properties,关于JDBC这里的更详细的配置,可以访问官网 database-authentication部分:

#数据库连接配置

cas.authn.jdbc.query[0].user=root

cas.authn.jdbc.query[0].password=mysql

cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver

cas.authn.jdbc.query[0].url=jdbc:mysql://localhost:3306/cas_auth

cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect

##从数据库中获取用户名和密码进行匹配登录

cas.authn.jdbc.query[0].sql=SELECT * FROM `user` WHERE userName=?

cas.authn.jdbc.query[0].fieldPassword=password

e 重新构建项目并启动,输入数据库中存在的用户名和密码,是可以成功登录的;

⑤、cas服务端搭建(整合Shiro和SpringBoot)

新建maven项目,引入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<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"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>gdou.laixiaoming</groupId><artifactId>cas-client-a</artifactId><version>0.0.1-SNAPSHOT</version><name>cas-client-a</name><description>CAS Client Demo.</description><properties><java.version>1.8</java.version><shiro.version>1.4.0</shiro.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- shiro --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-cas</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-aspectj</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

shiro配置

扩展CasRealm,在登录成功后,可以获取到登录的用户名,在客户端这边再把用户拥有的角色和权限查询出来并保存:
public class MyCasRealm extends CasRealm{@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//获取用户名String username = (String)principals.getPrimaryPrincipal();SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//        authorizationInfo.setRoles(new HashSet<>(Arrays.asList("admin")));
//        authorizationInfo.setStringPermissions(new HashSet<>(Arrays.asList("admin")));return authorizationInfo;}
}Shiro配置:
@Configuration
public class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);//配置自定义casFilterMap<String, Filter> filters = new LinkedHashMap<>();CasFilter casFilter = new CasFilter();casFilter.setFailureUrl("/casFailure");filters.put("cas", casFilter);shiroFilterFactoryBean.setFilters(filters);//配置filter调用链Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//anon为匿名,不拦截filterChainDefinitionMap.put("/static/**", "anon");filterChainDefinitionMap.put("/casFailure", "anon");//拦截CAS Server返回的ticketfilterChainDefinitionMap.put("/cas", "cas");//退出登录filterChainDefinitionMap.put("/logout", "anon");filterChainDefinitionMap.put("/logouttips", "anon");//需要登录访问的页面filterChainDefinitionMap.put("/**", "user");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//service指定了登录成功后的回调地址,回调/cas将被CasFilter拦截,获取服务端返回的Service Ticket进行登录shiroFilterFactoryBean.setLoginUrl("https://www.xiaoti.com:8443/cas/login?service=http://www.localhost1.com:9090/cas");//登录成功后要跳转的链接shiroFilterFactoryBean.setSuccessUrl("/");//未授权跳转页面shiroFilterFactoryBean.setUnauthorizedUrl("/403");return shiroFilterFactoryBean;}@Beanpublic MyCasRealm casRealm(){//使用自定义RealmMyCasRealm casRealm = new MyCasRealm();casRealm.setCachingEnabled(true);casRealm.setAuthenticationCachingEnabled(true);casRealm.setAuthenticationCacheName("authenticationCache");casRealm.setAuthorizationCachingEnabled(true);casRealm.setAuthorizationCacheName("authorizationCache");//指定CAS服务端地址casRealm.setCasServerUrlPrefix("https://www.xiaoti.com:8443/cas");//当前应用的CAS服务URL,用于接收和处理CAS服务端的TicketcasRealm.setCasService("http://www.localhost1.com:9090/cas");return casRealm;}@Beanpublic SecurityManager securityManager(){DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();securityManager.setRealm(casRealm());return securityManager;}/*** Shiro生命周期处理器*/@Beanpublic LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}@Bean@DependsOn({"lifecycleBeanPostProcessor"})public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();advisorAutoProxyCreator.setProxyTargetClass(true);return advisorAutoProxyCreator;}/*** 开启Shiro AOP的注解支持(如@RequiresRoles,@RequiresPermissions)*/@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);return authorizationAttributeSourceAdvisor;}}

⑥、cas单点登出配置

退出登录时,将页面重定向到CAS的退出页面,service参数的设置指定了退出登录后的回调地址:

@GetMapping("/logout")public String logout(){SecurityUtils.getSubject().logout();return "redirect:https://www.xiaoti.com:8443/cas/logout?service=https://www.xiaoti.com:9090/logouttips";}

service参数名可以在CAS服务端通过修改application.properties进行配置,关于登出的更多配置,可见官网:

#单点登出

#配置允许登出后跳转到指定页面

cas.logout.followServiceRedirects=true

#跳转到指定页面需要的参数名为 service

cas.logout.redirectParameter=service

在CAS服务端退出后,会向注册的每个服务发送登出请求,该请求可以由SingleSignOutFilter进行拦截并销毁当前会话:

@Configuration
public class CasConfig {@Beanpublic FilterRegistrationBean singleSignOutFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean(new SingleSignOutFilter());registration.addUrlPatterns("/*");return registration;}@Beanpublic ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutListenerRegistration() {ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> registration =new ServletListenerRegistrationBean<>(new SingleSignOutHttpSessionListener());return registration;}
}

⑥、cas单点登出配置

退出登录时,将页面重定向到CAS的退出页面,service参数的设置指定了退出登录后的回调地址:

@GetMapping("/logout")

         public String logout(){

                   SecurityUtils.getSubject().logout();

                   return "redirect:https://www.xiaoti.com:8443/cas/logout?service=https://www.xiaoti.com:9090/logouttips";

         }

#单点登出

#配置允许登出后跳转到指定页面

cas.logout.followServiceRedirects=true

#跳转到指定页面需要的参数名为 service

cas.logout.redirectParameter=service

在CAS服务端退出后,会向注册的每个服务发送登出请求,该请求可以由SingleSignOutFilter进行拦截并销毁当前会话:

@Configuration

public class CasConfig {

  

    @Bean

    public FilterRegistrationBean singleSignOutFilterRegistration() {

        FilterRegistrationBean registration = new FilterRegistrationBean(new SingleSignOutFilter());

        registration.addUrlPatterns("/*");

        return registration;

    }

  

    @Bean

    public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutListenerRegistration() {

        ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> registration =

                new ServletListenerRegistrationBean<>(new SingleSignOutHttpSessionListener());

        return registration;

    }

}

⑦、cas服务端配置

客户端搭建好后,需要在CAS服务端上配置哪些服务可以注册到CAS服务端上,服务的管理也有许多方式,这里使用的JSON的方式,需要先在服务端引入相关依赖(更多说明见官网):

<dependency>

                            <groupId>org.apereo.cas</groupId>

                            <artifactId>cas-server-support-json-service-registry</artifactId>

                            <version>${cas.version}</version>

                   </dependency>

然后,在已经生成的war包中找到文件:

image.png

将文件复制到这个位置:

image.png

修改,serviceId指定允许注册的客户端,更多配置见官网:

{

  "@class" : "org.apereo.cas.services.RegexRegisteredService",

  "serviceId" : "^(https|imaps|http)://(www\\.localhost1\\.com:9090|www\\.localhost2\\.com:9091)/.*",

  "name" : "HTTPS and IMAPS",

  "id" : 10000001,

  "description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",

  "evaluationOrder" : 10000

}

同时在application.properties指定配置文件位置:

#客户端服务注册

cas.serviceRegistry.json.location=classpath:/services

至此,CAS客户端搭建完成了

三、项目结构图

image.png

四、补充

CAS全称为Central Authentication Service即中央认证服务,是一个企业多语言单点登录的解决方案,并努力去成为一个身份验证和授权需求的综合平台。

CAS是由Yale大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的单点登录解决方法(属于 Web SSO )。

CAS协议至少涉及三方:客户端Web浏览器,请求身份验证的Web应用程序和CAS服务器。 它也可能涉及后端服务,如数据库服务器,它没有自己的HTTP接口,但与Web应用程序进行通信。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/134335.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis缓存

1. Redis缓存相关问题 1.1 缓存穿透 缓存穿透是指查询一个数据库一定不存在的数据。 我们以前正常的使用Redis缓存的流程大致是&#xff1a; 1、数据查询首先进行缓存查询 2、如果数据存在则直接返回缓存数据 3、如果数据不存在&#xff0c;就对数据库进行查询&#xff0…

企业级数据仓库-数仓实战

数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01&#xff08;机器准备&#xff09; 准备好三台虚拟机&#xff0c;并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…

Llama2-Chinese项目:2.2-大语言模型词表扩充

因为原生LLaMA对中文的支持很弱&#xff0c;一个中文汉子往往被切分成多个token&#xff0c;因此需要对其进行中文词表扩展。思路通常是在中文语料库上训练一个中文tokenizer模型&#xff0c;然后将中文tokenizer与LLaMA原生tokenizer进行合并&#xff0c;最终得到一个扩展后的…

Docker网络学习

文章目录 Docker容器网络1.Docker为什么需要网络管理2. Docker网络简介3. 常见的网络类型4. docker 网络管理命令5.两种网络加入差异6.网络讲解docker Bridge 网络docker Host 网络docker Container 网络docker none 网络 Docker容器网络 1.Docker为什么需要网络管理 容器的网…

自动生成bug异常追踪-SRE与开发自动化协同

作者&#xff1a;观测云 数据智能部 产品方案架构师 范莹莹 简介 生产环境 bug 的定义&#xff1a;RUM 应用和 APM 应用的 error_stack 信息被捕捉后成为 bug。 以 APM 新增错误巡检为例&#xff0c;当出现新错误时&#xff0c;在观测云控制台的「事件」模块下生成新的事件报…

基于matlab实现的电力系统稳定性分析摆幅曲线代码

完整程序&#xff1a; clear; clc; t 0; tf 0; tfl 0.5; tc 0.5; % tc 0.05, 0.125, 0.5 sec for 2.5 cycles, 6.25 cycles & 25 cycles resp ts 0.05; m 2.52 / (180 * 50); i 2; dt 21.64 * pi / 180; ddt 0; time(1) 0; ang(1) 21.64; pm 0.9; pm1 2.44;…

java 字符串只保留数字、字母、中文

public static void main(String[] args) {String str "测 试 WG23-D";// 只留字母String s1 str.replaceAll("[^a-zA-Z]", "");// 只留数字String s2 str.replaceAll("[^0-9]", "");// 只留中文String s3 str.replaceA…

骨传导耳机有害处吗、骨传导耳机真的不好用吗?

骨传导耳机没有害处。 骨传导耳机是通过将声音传递到颅骨&#xff0c;再由颅骨传递到内耳&#xff0c;从而达到听声音的效果&#xff0c;与传统的耳机不同。 因此&#xff0c;骨传导耳机不会直接对人的身体健康、耳朵产生压力和损伤&#xff0c;也不会影响耳道和中耳的正常功能…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

题目 1057: 二级C语言-分段函数

有一个函数如下&#xff0c;写一程序&#xff0c;输入x&#xff0c;输出y值。 保留两位小数 样例输入 1 样例输出 1.00 这道题的思路很简单&#xff0c;我直接用if判断输入的X对应的函数Y的区间&#xff0c;代入对应的函数&#xff0c;求出结果。记得变量用浮点型&#xff…

【毕设选题】opencv 图像识别 指纹识别 - python

文章目录 0 前言1 课题背景2 效果展示3 具体实现3.1 图像对比过滤3.2 图像二值化3.3 图像侵蚀细化3.4 图像增强3.5 特征点检测 4 OpenCV5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往…

计算机竞赛 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

基于springboot+vue的问卷调查系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

Day42:网易云项目,路由进阶

网易云项目 创建、启动项目并配置路由 npm init vite npm i npm i vue-router npm i sass -D 在main.js中 import router from ./router createApp(App).use(router).mount(#app) 在index中配置路由 import {createRouter,createWebHistory} from vue-router import H…

【第200篇原创文章】解决低于1%概率出现的芯片VPSS模块跑飞的问题

在发布SDK内测的时候&#xff0c;我们发现在切换视频分辨率的时候有低概率出现VPSS模块跑飞的情况&#xff0c;概率低于1%&#xff0c;试个两三百次&#xff0c;能出1~2次。切换视频分辨率这个功能在安防产品上也确实存在需求&#xff0c;网络带宽不大好的地方分辨率可以适当下…

【LeetCode-面试经典150题-day24】

目录 35.搜索插入位置 74.搜索二维矩阵 162.寻找峰值 33.搜索旋转排序数组 35.搜索插入位置 题意&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请…

Verdi实现信号的平移

在Verilog/System verilog中&#xff0c;# xxx可以实现延迟指定时间的功能&#xff0c;而在使用verdi查看信号波形并进行分析时&#xff0c;同样也可以实现类似的功能。 (注&#xff1a;这种信号平移是有其应用场景的&#xff0c;例如&#xff0c;在某些仿真模型中&#xff0c;…

【100天精通Python】Day63:Python可视化_Matplotlib绘制子图,子图网格布局属性设置等示例+代码

目录 1 基本子图绘制示例 2 子图网格布局 3 调整子图的尺寸 4 多行多列的子图布局 5 子图之间的共享轴 6 绘制多个子图类型 7 实战&#xff1a; 绘制一个大图&#xff0c;里面包含6个不同类别的子图&#xff0c;不均匀布局。 绘制子图&#xff08;subplots&#xff09;…

趣谈网络协议_1

趣谈网络协议_1 第1讲 | 为什么要学习网络协议&#xff1f;第4讲 | DHCP与PXE&#xff1a;IP是怎么来的&#xff0c;又是怎么没的&#xff1f;动态主机配置协议&#xff08;DHCP&#xff09; 第5讲 | 从物理层到MAC层&#xff1a;如何在宿舍里自己组网玩联机游戏&#xff1f;第…

C# 随机数生成 Mersenne Twister 马特赛特旋转演算法 梅森旋转算法

NuGet安装MathNet.Numerics 引用: using MathNet.Numerics.Random; /// <summary>/// 包括lower&#xff0c;不包括upper/// </summary>/// <param name"lower"></param>/// <param name"upper"></param>/// <para…