SpringCloud之SSO单点登录-基于Gateway和OAuth2的跨系统统一认证和鉴权详解
单点登录(SSO)是一种身份验证过程,允许用户通过一次登录访问多个系统。本文将深入解析单点登录的原理,并详细介绍如何在Spring Cloud环境中实现单点登录。通过具体的架构图和代码示例,我们将展示SSO的工作机制和优势,帮助开发者更好地理解和应用这一技术。
一、单点登录简介
1、单点登录介绍
单点登录(Single Sign-On,简称SSO)是一种认证机制,允许用户通过一次身份验证后,访问多个相互信任的应用系统。它简化了用户的操作,提高了用户体验,同时也降低了管理多个认证系统的复杂性。在现代分布式系统和微服务架构中,SSO尤为重要,因为它可以减少重复的登录操作,统一用户认证入口,提高系统的安全性和可管理性。
2、单点登录原理
SSO的基本原理是通过共享认证状态来实现对多个系统的访问。其核心步骤包括:
- 用户认证:用户在SSO认证中心进行登录,认证中心验证用户身份后生成一个Token。
- Token共享:用户访问其他受信任的应用系统时,携带这个Token。应用系统通过验证Token来确认用户身份。
- 会话管理:SSO系统管理用户会话状态,确保用户在有效期内不需要重复登录。
3、单点登录架构图
二、单点登录实现
在Spring Cloud环境中实现单点登录需要考虑以下几个步骤:
步骤 | 描述 |
---|---|
1. 建立认证中心 | 创建一个专门的认证服务,负责用户登录和Token生成。可以使用Spring Security和OAuth2来实现这一功能。 |
2. 配置网关服务 | 通过Spring Cloud Gateway或Zuul来实现请求路由和Token验证。 |
3. 应用服务集成 | 将各个应用服务与认证中心集成,确保每个请求都经过Token验证。 |
1. 建立认证中心
认证中心负责用户认证和Token生成。可以使用Spring Security和OAuth2来实现认证中心。
OAuth2 协议介绍:
OAuth2 协议是一种授权框架,允许第三方应用在用户授权下,访问用户的资源而无需共享用户的凭据,常用于社交媒体登录等场景。
OAuth2 协议一共支持四种不同的授权模式:
- 授权码模式:大多数第三方平台登录功能都采用这种模式,因其具有较高的安全性。
- 简化模式:简化模式不需要第三方服务器(客户端)的参与,直接在浏览器中向授权服务器申请令牌(token)。如果网站是纯静态页面,可以采用这种方式。
- 密码模式:密码模式要求用户将用户名和密码直接提供给客户端,客户端再使用这些信息向授权服务器申请令牌(token)。这种模式需要用户对客户端有高度的信任,例如客户端应用和服务器提供商是同一家公司。
- 客户端模式:客户端模式是指客户端以自己的名义而非用户的名义向授权服务器申请授权。严格来说,客户端模式并不属于OAuth协议的典型解决方案,但在某些移动端授权服务器上使用这种模式对开发者来说非常方便。
最常用的是授权码模式,也是我们这里使用的模式。
OAuth2 授权码模式示意图:
为了更清晰地展示授权码模式的每个环节,我们可以使用Mermaid将流程分为几个部分。以下是分成四张图分别介绍每个环节的示例代码:
- Step 1: 用户请求资源并重定向到授权服务器
- Step 2: 用户同意授权并获取授权码
- Step 3: 客户端交换授权码获取访问令牌
- Step 4: 客户端使用访问令牌访问资源服务器
① 添加OAuth2依赖
给项目添加OAuth2依赖项:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
② 配置OAuth2认证服务器
创建并配置OAuth2认证服务器:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("client-id").secret("{noop}client-secret").authorizedGrantTypes("authorization_code", "refresh_token", "password").scopes("read", "write").redirectUris("http://localhost:8081/login/oauth2/code/custom");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager).tokenStore(new InMemoryTokenStore());}
}
③ 配置Spring Security
创建并配置Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("USER");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}
2. 配置网关服务
网关服务负责路由请求和验证Token。我们使用Spring Cloud Gateway来实现。
① 添加网关服务依赖
给项目添加网关服务依赖项:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
② 增加Gateway配置
在application.yml中添加Gateway配置:
spring:cloud:gateway:routes:- id: user-serviceuri: lb://USER-SERVICEpredicates:- Path=/user/**filters:- TokenRelaysecurity:oauth2:client:provider:custom:authorization-uri: http://localhost:8080/oauth/authorizetoken-uri: http://localhost:8080/oauth/tokenuser-info-uri: http://localhost:8080/userinfojwk-set-uri: http://localhost:8080/.well-known/jwks.jsonregistration:custom:client-id: client-idclient-secret: client-secretauthorization-grant-type: authorization_coderedirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"scope: read,write
3. 应用服务集成
每个微服务都需要配置为资源服务器,以确保每个请求都经过Token验证。
① 给每个服务添加依赖
给每个服务添加OAuth2资源服务器依赖项:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
② 给每个服务添加配置
在application.yml中添加OAuth2资源服务器配置:
spring:security:oauth2:resourceserver:jwt:issuer-uri: http://localhost:8080/
③ 配置安全策略
创建并配置Spring Security以确保所有请求都经过Token验证:
@Configuration
@EnableWebSecurity
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest().authenticated().and().oauth2ResourceServer().jwt();}
}
4、编写单点登录接口
在实现单点登录的过程中,涉及到客户端应用向认证中心请求认证并获取Token,然后将Token传递给各个微服务以进行资源访问。以下是单点登录调用代码的详细步骤,包括获取授权码、请求访问令牌以及使用令牌访问受保护资源的示例代码。
① 获取授权码
首先,客户端应用需要引导用户到SSO认证中心进行登录,并获取授权码。
可以通过浏览器重定向实现:
@GetMapping("/login")
public void login(HttpServletResponse response) throws IOException {String authorizationUri = "http://localhost:8080/oauth/authorize";String clientId = "client-id";String redirectUri = "http://localhost:8081/callback";String responseType = "code";String scope = "read write";String authUrl = authorizationUri + "?response_type=" + responseType+ "&client_id=" + clientId+ "&redirect_uri=" + URLEncoder.encode(redirectUri, "UTF-8")+ "&scope=" + URLEncoder.encode(scope, "UTF-8");response.sendRedirect(authUrl);
}
② 获取访问令牌
用户在认证中心成功登录后,认证中心会重定向回客户端应用,并附带授权码。
客户端应用需要使用这个授权码来请求访问令牌:
@GetMapping("/callback")
public String callback(@RequestParam("code") String code, Model model) {String tokenUri = "http://localhost:8080/oauth/token";String clientId = "client-id";String clientSecret = "client-secret";String redirectUri = "http://localhost:8081/callback";RestTemplate restTemplate = new RestTemplate();HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);headers.setBasicAuth(clientId, clientSecret);MultiValueMap<String, String> params = new LinkedMultiValueMap<>();params.add("grant_type", "authorization_code");params.add("code", code);params.add("redirect_uri", redirectUri);HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);ResponseEntity<Map> response = restTemplate.exchange(tokenUri, HttpMethod.POST, request, Map.class);Map<String, Object> responseBody = response.getBody();String accessToken = (String) responseBody.get("access_token");model.addAttribute("accessToken", accessToken);return "home";
}
③ 使用访问令牌访问受保护资源
获取访问令牌后,客户端应用可以使用这个令牌来访问受保护的资源。
以下是如何使用RestTemplate访问受保护资源的示例代码:
@GetMapping("/resource")
public String getResource(@RequestParam("accessToken") String accessToken, Model model) {String resourceUri = "http://localhost:8082/resource";RestTemplate restTemplate = new RestTemplate();HttpHeaders headers = new HttpHeaders();headers.setBearerAuth(accessToken);HttpEntity<String> request = new HttpEntity<>(headers);ResponseEntity<String> response = restTemplate.exchange(resourceUri, HttpMethod.GET, request, String.class);String resource = response.getBody();model.addAttribute("resource", resource);return "resource";
}
5、示例项目结构
示例项目结构如下:
/sso-auth-server├── src/main/java/com/example/auth│ ├── AuthorizationServerConfig.java│ ├── SecurityConfig.java│ └── Application.java└── src/main/resources└── application.yml/sso-gateway├── src/main/java/com/example/gateway│ └── Application.java└── src/main/resources└── application.yml/sso-user-service├── src/main/java/com/example/user│ ├── ResourceServerConfig.java│ └── Application.java└── src/main/resources└── application.yml/sso-client├── src/main/java/com/example/client│ ├── SsoController.java│ └── Application.java└── src/main/resources└── application.yml
这个结构包括四个主要部分:
- 认证服务器 (sso-auth-server):负责用户认证和Token生成。
- 网关服务 (sso-gateway):负责路由请求和Token验证。
- 用户服务 (sso-user-service):作为资源服务器,提供受保护的资源。
- 客户端应用 (sso-client):负责引导用户登录、获取Token并访问受保护资源。
三、单点登录总结
1、单点登录的优势
优势 | 描述 |
---|---|
用户体验提升 | 用户只需一次登录即可访问所有系统,避免了重复登录的繁琐操作。 |
安全性增强 | 统一的认证入口和集中式管理可以提高系统的安全性,减少各个系统独立管理认证信息的风险。 |
管理简化 | 集中管理用户身份信息和认证逻辑,简化了系统的维护和管理工作。 |
提高生产力 | 减少了用户在不同系统之间切换的时间,进而提升了整体工作效率。 |
降低开发成本 | 开发者只需实现一次认证和授权逻辑,可以节省开发和维护多个认证系统的成本。 |
统一用户管理 | 用户数据和权限集中存储和管理,使得用户信息更新和权限变更更加便捷高效。 |
改善审计和合规性 | 集中的认证和授权机制有助于监控用户行为,满足法规和审计的要求。 |
便于集成扩展 | 可以方便地集成新的应用系统,无需为每个新系统单独配置登录和认证流程。 |
2、单点登录总结
单点登录(Single Sign-On, SSO)在现代分布式系统中扮演着重要角色,它不仅提高了用户体验,还增强了系统的安全性。通过Spring Cloud实现SSO,可以充分利用Spring的生态系统和强大的功能,实现高效的身份认证和授权管理。
在实际应用中,开发者应根据具体需求和系统架构选择合适的实现方案,并不断优化以提高系统性能和安全性。以下是一些关键点:
- 技术选型:选择适合业务需求的SSO实现方式,如基于OAuth2、JWT或CAS等。
- 安全策略:确保数据传输和存储的安全,采用加密技术保护用户信息,防范攻击。
- 性能优化:通过负载均衡、缓存和异步处理等技术提升系统的响应速度和稳定性。
- 用户管理:集中管理用户身份信息,确保用户数据的一致性和准确性。
- 日志和监控:实施全面的日志记录和监控机制,及时发现和处理潜在问题,确保系统的正常运行。
- 容错机制:设计健壮的容错机制,确保系统在出现故障时能够快速恢复。
通过以上措施,可以有效提升单点登录系统的整体表现,满足企业的业务需求和安全要求。
相关文章:

SpringCloud之SSO单点登录-基于Gateway和OAuth2的跨系统统一认证和鉴权详解
单点登录(SSO)是一种身份验证过程,允许用户通过一次登录访问多个系统。本文将深入解析单点登录的原理,并详细介绍如何在Spring Cloud环境中实现单点登录。通过具体的架构图和代码示例,我们将展示SSO的工作机制和优势&a…...
二分查找算法详讲(三种版本写法)原创
介绍: 二分查找算法(Binary Search)是一种在有序数组中查找目标元素的算法。 它的基本思想是通过将目标元素与数组的中间元素进行比较,从而将搜索范围缩小一半。 如果目标元素等于中间元素,则搜索结束;如果目标元素小…...
Git钩子(Hooks)之commit之前自动执行脚本
介绍 官方文档: 英文:https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks中文:https://git-scm.com/book/zh/v2/自定义-Git-Git-钩子 下面只复制了pre-commit部分文档,其他详见官方文档。 Git Hooks Like many other…...

nano机器人2:机械臂的视觉抓取
前言 参考链接: 【机械臂入门教程】机械臂视觉抓取从理论到实战 GRCNN 通过神经网络,先进行模型训练,在进行模型评估。 机械臂逆运动学求解 所有串联型6自由度机械臂均是可解的,但这种解通常只能通过数值解法得到,计算难度大&am…...
技术速递|宣布 Java on Azure 开发工具支持 Java on Azure Container Apps
作者:Jialuo Gan 排版:Alan Wang 在 Microsoft Build 2024 期间宣布,Azure Container Apps 现在可为 Java 开发人员提供丰富的操作功能。(详细内容请参见本博客)。 我们很高兴地与大家分享,Azure Toolkit for Intelli…...

随机森林算法实现分类
随机森林算法实现对编码后二进制数据的识别 1.直接先上代码! import numpy as np import pandas as pd from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import …...
Ubuntu卸载软件
在删除这些目录之前,你必须确定一个非常重要的事情:确认没有任何服务正在使用这些版本的 PHP。如果你删除了正在使用的 PHP 版本的扩展目录,那么依赖于这个版本的 PHP 的网站或服务可能会停止工作。 如果你确定某个版本的 PHP 没有在使用中&…...
网络工程师:网络可靠性技术
一、可靠性 平均故障间隔时间MTBF(Mean Time Between Failure)和平均修复时间MTTR(Mean Time to Repair)这两个指标来评价系统的可靠性。 1、平均故障间隔时间MTBF MTBF是指一个系统无故障运行平均时间,通常以小时为单位。MTBF越大可靠性越高。 2、平均修复时间MTTR…...

科技引领未来:高速公路可视化
高速公路可视化监控系统利用实时视频、传感器数据和大数据分析,通过图扑 HT 可视化展示交通流量、车速、事故和路况信息。交通管理人员可以实时监控、快速响应突发事件,并优化交通信号和指挥方案。这一系统不仅提高了道路安全性和车辆通行效率࿰…...
Golang发送POST请求并传递JSON数据
客户端 package mainimport ("c02_get_param/common""fmt""zdpgo_resty" )func main() {// Create a Resty Clientclient : zdpgo_resty.New()// 设置字符串resp, err : client.R().SetHeader("Content-Type", "application/jso…...
C++实现生产者消费者模型
生产者-消费者模型是一种典型的多线程并发模式,常用于在一个共享缓冲区中协调生产者和消费者之间的数据传递。在C中,我们可以使用标准库中的线程、互斥量和条件变量来实现该模型。以下是一个简单的生产者-消费者模型的实现示例: #include &l…...

【Mac】MWeb Pro(好用的markdown编辑器) v4.5.9中文版安装教程
软件介绍 MWeb Pro for Mac是一款Mac上的Markdown编辑器软件,它支持实时预览,语法高亮,自动保存和备份等功能,并且有多种主题和样式可供选择。此外,MWeb还支持多种导出格式,包括HTML、PDF、Word、ePub等&a…...

C++ | Leetcode C++题解之第118题杨辉三角
题目: 题解: class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> ret(numRows);for (int i 0; i < numRows; i) {ret[i].resize(i 1);ret[i][0] ret[i][i] 1;for (int j 1; j &…...

3D透视图转的时候模型闪动怎么解决?---模大狮模型网
在3D建模与渲染的世界中,透视图是我们观察和操作模型的重要窗口。然而,有时候在旋转透视图时,模型会出现闪动的现象,这不仅影响了我们的工作效率,还可能对最终的渲染效果产生负面影响。本文将探讨这一问题的成因&#…...

如何创建一个vue项目?详细教程,如何创建第一个vue项目?
已经安装node.js在自己找的到的地方新建一个文件夹用于存放项目,记住文件夹的存放路径,以我为例,我的文件夹路径为D:\tydic 打开cmd命令窗口,进入刚刚的新建文件夹 切换硬盘: D: 进入文件夹:cd tydic 使…...
AWS迁移与传输之Migration Hub
AWS Migration Hub是一种集中化的迁移管理服务,可帮助企业规划、跟踪和管理在亚马逊云中进行的各种迁移活动。包括应用程序迁移、数据库迁移、服务器迁移等。 AWS Migration Hub (Migration Hub) 提供一个位置来跟踪使用多个 AWS 工具和合作伙伴解决方案的迁移任务…...
网络渗透思考
1. windows登录的明文密码,存储过程是怎么样的,密文存在哪个文件下,该文件是否可以打开,并且查看到密文 windows的明文密码:是通过LSA(Local Security Authority)进行存储加密的 存储过程:当用户输入密码之…...

2.8万字总结:金融核心系统数据库升级路径与场景实践
OceanBase CEO 杨冰 谈及数字化转型,如果说过去还只是头部金融机构带动效应下的“选择题”。那么现在,我相信数字化转型已经成为不论大、中、小型金融机构的“必答题”。 本文为OceanBase最新发布的《万字总结:金融核心系统数据库升级路径…...

Linux:进程控制(二.详细讲解进程程序替换)
上次讲了:Linux:进程地址空间、进程控制(一.进程创建、进程终止、进程等待) 文章目录 1.进程程序替换1.1概念1.2原理1.3使用一个exec 系列函数execl()函数结论与细节 2.多进程时的程序替换3.其他几个exec系…...

Elasticsearch8.13.4版本的Docker启动关闭HTTPS
博主环境是: 开发环境:SpringbootElasticSearch客户端对应的starter 2.6.3版本 maven配置 <!-- ElasticSearch --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elas…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...