Auth2.0单点登录(企业开发流程)

news2024/10/9 9:01:33

实习中接到需求单点登录,记录一下单点登录在企业中的实际应用。其实单点登录在不同的业务中处理细节还是不相同的,我这里仅举例我们这个需求中如何处理的一种情形。

一.概念

简单来说就是一次登录,各处访问。

二.流程

场景一: 用户采取三方登录。

场景一的流程:
  • 用户采用三方登录方式,点击访问三方应用的认证方式
  • 访问认证服务器,用户登录三方的登录界面,登录完成后,点击授权,此时将会根据我们配置的回调地址,携带授权后生成的code.回调访问
  • 随后服务器接收到回调的请求,拿到对应的code,携带这个code再去认证服务器获取token.
  • 获取到token后,再向资源服务器获取用户信息。
  • 解析返回回来的用户信息,完成登录。

背景:三方的数据已同步到本地,这样才有本地的映射。没有也没有关系,根据具体的业务更改逻辑即可。

具体流程

  1. 首先通过redirect_uri注册到资源认证服务器。获取到注册在资源服务器的client_id与client_secret.
  2. 随后访问自己产品的登录界面,配置资源认证服务器的url,对应前端来讲就是一个三方按钮。例如gitee中登录界面中下面的其他软件的登录方式。

  1. 之后我们将携带一系列的参数去访问这个url, 主要参数为
  • client_id: 注册在认证服务器的id
  • client_secret: 注册在认证服务器的secret
  • redirect_uri: 获取code后的回调地址。

  1. 用户在三方完成登录后将会根据回调地址redirect_uri,拼接code参数。打回到本地服务器。
  2. 随后本地服务器将会发送两个http请求。
    1. 一个携带我们获取到的code,去三方服务器获取token
    2. 拿到token后,发送第二个http请求。获取用户信息。
  1. 获取到用户信息后,匹配本地的数据库信息,例如userInfo会返回回来一个字段,能够唯一标识一个用户。根据这个标识我们在本地做一个映射,映射到我们本地服务器数据库存储用户信息的一个字段。查询到用户信息。
  2. 返回用户信息到客户端,完成登录。

我在实现的时候,采取了配置的形式,会在回调地址中拼接一个配置参数。例如sso_code=xxx,利用这个配置我们可以去数据库查询到具体的配置结构。

对应的类

public class Auth2SSOLoginConfig implements Serializable {
    /**
     * sso服务端名称
     */
    private String name;
    /**
     * sso配置唯一id
     */
    private String ssoCode;
    /**
     * 拼接token参数名
     */
    private String tokenKey;
    /**
     * code参数名
     */
    private String codeKey;

    /**
     * token配置
     */
    private HttpContentConfig token;
    /**
     * userinfo配置
     */
    private HttpContentConfig userinfo;


}

HttpContentConfig

@Data
public class HttpContentConfig {
    private HttpRequestConfig requestConfig;
    private SSOResultConfig ssoResultConfig;


    @Data
    public static class HttpRequestConfig{
        private String url;

        private String method;

        private Map<String,String> header;

        private Map<String,Object> params;

        private Map<String,Object> paramsMapping;
    }


    @Data
    public static class SSOResultConfig {

        /**
         * code 解析的path
         */
        private String codePath;

        /**
         * code 成功值,状态码
         */
        private String codeSuccessValue;

        /**
         * 参数映射
         */
        private Map<String,String> valueMapping;

    }
}

数据库表结构为

字段名

类型

描述

id

bigint

自增主键

name

varchar(63)

SSO服务端名

sso_code

varchar(63)

配置唯一id

config

text

配置内容

gmt_create

timestamp

创建时间

gmt_update

timestamp

更新时间

gmt_delete

timestamp

删除时间

create_operator

varchar(255)

创建人

update_operator

varchar(255)

更新人

delete_operator

varchar(255)

删除人

is_delete

boolean

逻辑删除字段

config的结构为一个大Json

{
  "token": {
    "requestConfig": {
      "url": "http://localhost:8080/demo/code",
      "method": "POST",
      "header": [
        {
          "Content-Type": "application/x-www-form-urlencoded",
          "Accept": "text/html,application/xhtml+xml,application/xml"
        }
      ],
      "params": {
        "grant_type": "authorization_code",
        "client_id": "",
        "client_secret": "",
        "redirect_uri": "",
        "endpoint_uri": ""
      }
    },
    "ssoResultConfig": {
      "codeSuccessValue": "",
      "codePath": "",
      "valueMapping": {
        "access_token": "access_token",
        "refresh_token": "refresh_token",
        "scope": "scope",
        "token_type": "token_type",
        "expires_in": "expires_in"
      },
      "paramsMapping": {
        "code": "code"
      }
    }
  },
  "userInfo": {
    "requestConfig": {
      "url": "http://localhost:8080/demo/token",
      "method": "POST",
      "header": [
        {
          "Content-Type": "application/x-www-form-urlencoded",
          "Accept": "text/html,application/xhtml+xml,application/xml"
        }
      ],
      "params": {
        "client_id": "",
        "client_secret": "",
        "endpoint_uri": ""
      },
      "paramsMapping": {
        "token": "token"
      }
    },
    "ssoResultConfig": {
      "codeSuccessValue": "",
      "codePath": "",
      "valueMapping": {
        "scope": "scope",
        "active": "active",
        "token_type": "token_type",
        "exp": "exp",
        "iat": "iat",
        "client_id": "client_id",
        "account": "username"
      }
    }
  },
  "codeKey": "code",
  "tokenKey": "token"
}

这里解释一下codeKey,tokenKey与paramsMapping中的code与token的差别与作用。

codeKey是我们去动态解析响应的结果的参数名。这样配置以后获取是不叫code,只需要改配置解析即可。

而tokenKey是场景二的使用,待会再解释。

而paramsMapping中的code与token是我们拼接参数值的参数名。作用也是可以动态配置解析,以后参数名变更我们只需要改配置即可。

场景二的流程:

场景二:

用户已在三方登录完成,访问本地产品页面

  • 检验本地session中用户信息是否存在
  • 存在直接登录。不存在查询配置
  • 获取所有的配置,拿到对应的Map,key为tokenKey,value为token对应的配置
  • 查询cookie当中是否存在tokenKey
  • 存在直接携带此token与配置获取用户信息
  • 不存在直接重定向回登录页面。

这是我们需要去拦截器去完成的一个过程。

这里需要了解一个知识,我们可以通过设置cookiedomain,来保证双方的cookie互通,

比如

A网址 org.example.com

B网址 www.example.com

我们设置domain为example.com这样会把这样设置的cookie共同传递到两个网址。我们再根据我们配置的tokenKey就能够正常拿到对应的tokenValue。然后剩下的流程其实就是我们场景一有了token之后的过程。

然后我们在拦截器大致就是这样一个处理逻辑,如下。

private boolean checkSSOLogin(HttpServletRequest request, HttpServletResponse response) {
    Map<String, Auth2SSOLoginConfig> allConfig = ssoAuth2LoginManager.getAllConfig();
    if(MapUtils.isEmpty(allConfig)){
        return false;
    }
    Set<String> keySet = allConfig.keySet();
    String tokenValue = null;
    String tokenKey = null;
    for (Cookie cookie : request.getCookies()) {
        if (keySet.contains(cookie.getName())) {
            tokenKey = cookie.getName();
            tokenValue = cookie.getValue();
            break;
        }
    }
    if (StringUtils.isNotBlank(tokenValue)) {
        UserDTO userDTO = userManager.getUserDTOForTokenAndUserInfo(allConfig.get(tokenKey), tokenValue);
        HttpSession session = request.getSession();
        //在session域中记录信息,并在SessionId中记录信息
        userHelper.writeUserIntoToSession(userDTO, session);
        return true;
    }
    return false;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring源码二IOC容器源码

文章目录 Spring IOC初始化源码剖析1.prepareRefresh2.obtainFreshBeanFactory3.prepareBeanFactory4.postProcessBeanFactory5.invokeBeanFactoryPostProcessors6.registerBeanPostProcessors7.initMessageSource8.initApplicationEventMulticaster9.onRefresh10.registerList…

Day05-数据库服务索引应用

Day-05-数据库索引知识说明 1、数据库索引概述介绍2、数据库索引分类介绍3、数据库索引应用配置4、数据库执行计划概述5、数据库执行计划获取7、数据库索引覆盖长度8、数据库联合索引应用 01.数据库索引概述介绍 02.数据库索引分类介绍 03.数据库索引应用配置 04.数据库执行计划…

C高级(Day25)

一、学习内容 Shell脚本 shell中的变量 shell中变量的定义 shell中的变量是没有数据类型的&#xff0c;&#xff0c;默认是字符串 shell中的变量默认是全局变量 格式 变量名 错误&#xff0c;计算机认为变量名是一个指令 变量名 正确&#xff0c;定义变量 &#xff0c;值为空…

基于Springboot+Vue的公寓出租系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

成都睿明智科技有限公司靠谱吗怎么样?

在这个短视频与直播带货风起云涌的时代&#xff0c;抖音电商凭借其庞大的用户基数和高效的流量转化能力&#xff0c;成为了众多商家争相入驻的新蓝海。而在这场电商盛宴中&#xff0c;专业的服务商如成都睿明智科技有限公司&#xff0c;更是成为了连接品牌与消费者的桥梁。那么…

Win10 安装 Redis 数据库

一、Redis 数据库介绍 Redis 是一个开源的高性能键值对&#xff08;key-value&#xff09;的非关系型数据库。它通常用作数据结构服务器&#xff0c;支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、哈希&#xff08;hashes&#xff09;、列表&a…

同城O2O系统源码与跑腿配送平台的架构设计与开发方案详解

今天&#xff0c;笔者将与您一同深入探讨同城O2O系统的源码及跑腿配送平台的架构设计与开发方案&#xff0c;助力开发者和企业在这一领域的实践与探索。 一、O2O系统概述 在同城O2O模式中&#xff0c;用户可以通过手机应用或网页平台下单&#xff0c;而配送员则根据订单信息迅…

redis高级(面试题一)

目录 一、Redis持久化机制有哪些&#xff1f;有什么区别&#xff1f; 1、RDB(redis database) 2、AOF 3、区别 二、redis的主从集群有什么用&#xff1f; 1、什么是redis的主从集群 2、为什么要使用redis主从集群&#xff08;也就是有什么用&#xff09; 三、redis的哨兵…

ORA-19815 db_recovery_file_dest_size 100%

1、alert日志报错 ORA-19815 db_recovery_file_dest_size 100% 恢复区空间使用满 2、rm删除后操作系统空间使用&#xff0c;但V$RECOVERY_FILE_DEST记录的空间使用率仍然是满的 3、rman delete expired 归档日志后恢复正常 4、当然可以通过增大db_recovery_file_dest_size来临时…

算法笔记(十四)——多源 BFS

文章目录 <font colorred>01 矩阵<font colorred>飞地的数量/font>地图中的最高点地图分析 多源 BFS 单源最短路问题&#xff1a;一个起点到一个终点的最短路&#xff1b; 解决步骤&#xff1a; 把起点放进队列里一层一层往外扩 相关文章&#xff1a;算法笔记&a…

0基础跟德姆(dom)一起学AI 机器学习04-逻辑回归

逻辑回归简介 应用场景 逻辑回归是解决二分类问题的利器 数学知识 sigmoid函数 概率 极大似然估计 核心思想&#xff1a; 设模型中含有待估参数w&#xff0c;可以取很多值。已经知道了样本观测值&#xff0c;从w的一切可能值中&#xff08;选出一个使该观察值出现的概率为…

C++拾趣——绘制Console中DropdownMenu

大纲 居中显示窗口清屏并重设光标绘制窗口绘制窗口顶部绘制下拉行绘制下拉框选项绘制按钮行绘制窗口底部 修改终端默认行为对方向键的特殊处理过程控制Tab键的处理Enter键的处理上下左右方向键的处理 完整代码代码地址 这次我们要绘制下拉菜单&#xff0c;如下图。 居中显示窗口…

C语言 | Leetcode C语言题解之第466题统计重复个数

题目&#xff1a; 题解&#xff1a; #include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <string.h> #include <math.h> #include <limits.h>#define MMAX(a, b) ((a) > (b)? (a) : (b)) #define MMIN(a,…

xianshan分支预测器BPU

xianshan分支预测器BPU 1 RISC-V分支预测1.0 分支预测基本类型1.0.1 条件分支指令1.0.2 无条件分支指令 1.1 方向预测1.1.1 饱和计数器法1.1.1.1 Questions 1.1.2 分支历史法--程序局部性原理1.1.2.1 Questions 1.2 目标地址预测1.2.1 分支目标缓存--BTB 1.3 预测指令类型1.3.1…

【小白向】机器人入门之ROS系统的学习(Ubuntu24.04+ROS2)

目录 一.复杂的机器人系统 二.ROS机器人系统 1.简介 1.节点 2.话题 2.安装 3.测试 4.可视化 RQT&#xff1a; RVIZ&#xff1a; 显示属性&#xff1a; 显示状态&#xff1a; 一.复杂的机器人系统 依照我们现在的技术来看&#xff0c;机器人系统仍是极其复杂的&#xff0c;往…

深入了解音频剪辑在线工具的特色与优势

在数字时代&#xff0c;音频内容已成为连接人心的重要桥梁。如果你也有同样的兴趣爱好&#xff0c;那不妨看看我今天要介绍的音频剪辑在线相关的工具们吧。 1.福昕音频剪辑 链接直达>>https://www.foxitsoftware.cn/audio-clip/ 福昕音频剪辑工具&#xff0c;专为音乐…

【H2O2|全栈】关于CSS(11)flex——更加优雅的布局

目录 CSS3入门 前言 准备工作 布局优化 如何使用flex布局 容器与成员 概念 轴线 容器的属性 成员的属性 预告和回顾 后话 CSS3入门 前言 本系列博客主要介绍CSS有关知识点&#xff0c;当前章节讲述CSS3相关内容。 本章节讲述flex布局的相关知识。 部分内容仅代…

数据结构 ——— 单链表oj题:环形链表

目录 题目要求 手搓简易环状单链表 代码实现 问题1&#xff1a;slow 指针和 fast 指针一定会相遇吗 问题2&#xff1a;slow 每次走一步&#xff0c;fast 每次走 n 步是否还能判断链表带环&#xff1f;&#xff08;n > 2&#xff09; 题目要求 有一个单链表的头节点 …

【翻译】在 Python 应用程序中使用Qt Designer的UI文件

原文地址&#xff1a;Using a Designer UI File in Your Qt for Python Application 直接上图&#xff0c;上代码 将UI文件转为Python To demonstrate, we use the Qt Widgets animation easing example. 为了演示&#xff0c;我们使用 Qt Widgets 动画简化示例。 这个应用程…

快递查询软件:实现单号识别与批量物流查询的高效工具

随着网络购物的普及&#xff0c;快递物流行业迎来了前所未有的发展机遇&#xff0c;同时也面临着巨大的挑战。跟踪物流信息成为一个难题&#xff0c;因此&#xff0c;快递查询软件的核心功能之一便是单号识别。传统的快递单号输入方式繁琐且易出错在此背景下&#xff0c;快递查…