单点登录平台设计

news2024/11/16 0:03:29

1.基本介绍

1.1什么是单点登录

单点登录(Single Sign-On,简称SSO)是一种身份认证的解决方案,它允许用户只需一次登录即可访问多个应用程序或系统。在一个典型的SSO系统中,用户只需通过一次身份认证,就可以获得访问多个应用程序的授权,而不需要在每个应用程序中单独进行身份验证。

1.2单点登录的原理

单点登录(Single Sign-On,简称SSO)的实现原理通常涉及到以下几个步骤:

  • 用户登录认证:用户在访问第一个应用程序时,需要进行身份验证并登录系统。这个过程可以使用任何一种常规的认证方式,比如用户名和密码、二次验证等等。
  • 生成令牌:认证通过后,系统会生成一个安全令牌(Token),将它存储在用户的浏览器中,同时将该令牌的信息存储在SSO服务器中。
  • 传递令牌:当用户访问其他应用程序时,应用程序将向SSO服务器发送令牌验证请求。SSO服务器会检查浏览器中的令牌信息,并确认用户的身份。
  • 验证身份:如果令牌有效且用户已经进行过身份验证,SSO服务器会向应用程序返回一个授权令牌,授权用户访问该应用程序。
  • 访问应用程序:应用程序会使用授权令牌来验证用户的身份,并允许用户访问应用程序的资源。

需要注意的是,SSO服务器需要能够识别和验证来自不同应用程序的令牌。为了实现这一点,通常使用标准的认证协议,如OAuth、OpenID Connect等,这些协议为应用程序提供了一种标准的方式来与SSO服务器交互。此外,SSO服务器还需要实现一些安全机制来防止令牌被盗用或伪造,如Token加密、过期时间等等。

2.基于OpenID Connect的SSO实现

OpenID Connect 是一项在 OAuth 2.0 协议基础上构建的简单身份协议和开放式标准。 它使客户机应用程序依赖于 OpenID Connect 提供者执行的认证来验证用户身份。

OpenID Connect 使用 OAuth 2.0 进行认证和授权,然后构建用于唯一地标识用户的身份。 客户机还可以通过互操作和类似 REST 的方式从 OpenID Connect 提供者中获取关于用户的基本概要文件信

2.1单点登录流程

  • 用户1访问应用1,应用1判断用户未登录,发送302跳转并携带回调地址参数到SSO单点登录服务
  • 在SSO服务中,输入用户名和密码,登录SSO服务
  • SSO服务登录成功后,跳转到回调地址,并携带code参数到应用1
  • 应用1根据code参数,调用接口/oauth2/token 获取AccessToken IdToken信息,根据IdToken获取对应的用户信息,自动登录应用1
  • 用户1访问应用2,应用2判断用户未登录,发送302跳转并携带回调地址参数到SSO单点登录服务
  • SSO服务已登录,跳转到回调地址,并携带code参数到应用2
  • 应用2根据code参数,调用接口/oauth2/token 获取AccessToken IdToken信息,根据IdToken获取对应的用户信息,自动登录应用2

2.2客户端注册表

字段

字段类型

描述

id

varchar

主键,系统自动生成

archived

tinyint

用于标识客户端是否已存档(即实现逻辑删除),默认值为'0'(即未存档).
对该字段的具体使用请参考CustomJdbcClientDetailsService.java,在该类中,扩展了在查询client_details的SQL加上archived = 0条件 (扩展字段)

create_time

datetime

数据的创建时间,精确到秒,由数据库在插入数据时取当前系统时间自动生成(扩展字段)

updated_time

timestamp

数据的最后更新时间,由数据库自行更新维护

client_id

varchar

唯一,不能为空.
用于唯一标识每一个客户端(client); 在注册时必须填写(也可由服务端自动生成).
对于不同的grant_type,该字段都是必须的. 在实际应用中的另一个名称叫appKey,与client_id是同一个概念.

client_id_issued_at

timestamp

client_id的签发时间, 默认为数据创建时间

client_secret

varchar

用于指定客户端(client)的访问密匙; 在注册时必须填写(也可由服务端自动生成),加密保存.
对于不同的grant_type,该字段都是必须的. 在实际应用中的另一个名称叫appSecret,与client_secret是同一个概念.

client_secret_expires_at

datetime

client_secret的过期时间,null表示永不过期

client_name

varchar

客户端(client)的名称,一般是一个有业务意义的名称

client_authentication_methods

varchar

认证支持的方式,多个由逗号分隔; 如: client_secret_basic,client_secret_post; 一般指认证时传递client_secret支持哪些方式

authorization_grant_types

varchar

指定客户端支持的grant_type,可选值包括authorization_code,urn:ietf:params:oauth:grant-type:device_code,refresh_token, urn:ietf:params:oauth:grant-type:jwt-bearer,client_credentials, 若支持多个grant_type用逗号(,)分隔,如: "authorization_code,refresh_token".
在实际应用中,当注册时,该字段是一般由服务器端指定的,而不是由申请者去选择的,最常用的grant_type组合有: "authorization_code,refresh_token"(针对通过浏览器访问的客户端); "client_credentials"(针对另一个服务端的场景,不需要用户参与).
urn:ietf:params:oauth:grant-type:device_code与urn:ietf:params:oauth:grant-type:jwt-bearer是OAuth2.1中新增.

redirect_uris

varchar

OAuth2 认证后回调uri, 一般传递code, 多个由逗号分隔; 可为空, 当grant_type为authorization_code时, 在OAuth的流程中会使用并检查与注册时填写的redirect_uri是否一致. 下面分别说明:当grant_type=authorization_code时, 第一步 从 spring-oauth-server获取 'code'时客户端发起请求时必须有redirect_uri参数, 该参数的值必须与 web_server_redirect_uri的值一致. 第二步 用 'code' 换取 'access_token' 时客户也必须传递相同的redirect_uri.
在实际应用中, redirect_uris在注册时是必须填写的, 一般用来处理服务器返回的code, 验证state是否合法与通过code去换取access_token值.

post_logout_redirect_uris

varchar

OAuth2 退出时 post 的客户端重定向 uri; 可选 多个由逗号分隔, 一般在client注册时可填写

scopes

varchar

指定客户端申请的权限范围,可选值在OIDC协议中定义, 包括openid,profile,email,address,phone;若有多个值用逗号(,)分隔,如: "openid,email".
openid是必须有的,其他值若有则在获取的id_token中会包含对应的值.
在实际应该中, 该值一般由服务端指定, 常用的值为openid.

client_settings

varchar

客户端的各类设置, 如是否支持PKCE,用户授权(consent)确认是否必须等; 详见代码ClientSettings.java; 此字段存储JSON格式的数据值.

token_settings

varchar

对token的各类设置; 如 token有效期, refresh_token有效期等; 详见代码TokenSettings.java; 此字段存储JSON格式的数据值.

2.3获取Authorization Uri

http://sso-server.com/oauth2/authorize

参数

说明

response_type

code

固定值 'code'

scope

openid profile email

OIDC标准中定义的scope有: openid, profile, email, address, phone; 具体支持哪些由注册的client决定

client_id

客户端注册生成的client_id

redirect_uri

回调用于检查server端返回的 'code'与'state',并发起对 access_token 的调用

state

一个随机值, oauth-server 将原样返回,用于检测是否为跨站请求(CSRF)等

根据参数,最终生成地址如下:

http://sso-server.com/oauth2/authorize?response_type=code&scope=openid profile email&client_id=3b10c5b6a2534ed980767d5e03029f93&redirect_uri=http://localhost:8082/authorization_code_callback&state=0226f30c-d62d-4261-8241-c4971386f068

2.4获取access_token (grant_type=authorization_code)

使用grant_type=authorization_code 方式来获取access_token, 需要先获取code

  1. 请求URI: /oauth2/token POST
  2. 请求参数说明:

参数名

参数值

必须?

备注

client_id

{client_id}

client_secret

{client_secret}

grant_type

authorization_code

固定值

code

{code}

redirect_uri

{redirect_uri}

code_verifier

{code_verifier}

PKCE时必须

  1. 请求示例:

  curl --location 'http://localhost:8080/oauth2/token' \

  --header 'Content-Type: application/json' \

  --form 'client_id="client11"' \

  --form 'grant_type="authorization_code"' \

  --form 'redirect_uri="http://localhost:8083/oauth2/callback"' \

  --form 'code="-VEnyAcEflDxjMh4Hr-6YejZq4Mel5gihFy_FMyotDxLhILeMBQheJkL4mdJ0sKD_C8xpa_sMNGf_I2tYJIVki8a4ktT2QsHojhbV3HpbGLVhJ0qDc8kfXjWt7u_24QO"' \

  --form 'client_secret="secret22"'

  1. 响应
  • 正常 [200]

{

       "access_token": "7154afT_cxvLDq1naSg6Aq9ueSFSW8xRr5txryW5MlddRe7nV0RogTYwPsJc_rrRqwaIvLleerLhkjtIN2E2U-4J_BzvYNCsv8BVLqeerCObwgwpP3t__NMMUakzRL2i",

       "refresh_token": "TZ9tzVwE_VLoJxALUSw4A4A0Nj7SLSWXCc69U9rvNmSnqR8Hbz-1m4uHebJWsAK0sa7SDIR4SNXOB3iaM0p1bH_8EBrljoBApQgdYi1uYzcVwYq55OVV2RUHN2BJwfSr",

       "scope": "openid profile",

       "id_token": "eyJraWQiOiJzb3MtZWNjLWtpZDEiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJ1bml0eSIsImF1ZCI6IjZ1ck5MZ1I2b3NrMkU1NmVrcCIsInVwZGF0ZWRfYXQiOiIiLCJhenAiOiI2dXJOTGdSNm9zazJFNTZla3AiLCJhdXRoX3RpbWUiOjE2OTc3MDczNTQsImlzcyI6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MCIsIm5pY2tuYW1lIjoiIiwiZXhwIjoxNjk3NzA5MjA4LCJpYXQiOjE2OTc3MDc0MDgsImp0aSI6IjEyNTc0MjU2NTk4MDI2ODY2NzI3NDAwMTMxNjk5NDk0Iiwic2lkIjoidXdwN255RnJwdlNtWmlQS2hCdWVSVFZfcVRKYkN6ZjAyTmYwQTZGN1lrSSJ9.3w-7EY9SwKA-UkXlhDfD2BbSwP6nCSLZxNgKwhkkMY8YPbMkygbj374SmEmsit7NlpRXHCtW6ULZ9_IVZ9MTBg",

       "token_type": "Bearer",

       "expires_in": 3599

}

  • 异常 [401]

{

       "error": "invalid_grant"

}

2.5刷新access_token (grant_type=refresh_token)

用于在access_token要过期时换取新的access_token (grant_type需要有refresh_token)

  1. 请求URI: /oauth2/token POST
  2. 请求参数说明:

参数名

参数值

必须?

备注

client_id

{client_id}

client_secret

{client_secret}

grant_type

refresh_token

固定值

refresh_token

{refresh_token}

  1. 请求示例:

curl --location 'http://localhost:8080/oauth2/token' \

--header 'Content-Type: application/json' \

--form 'client_id="6urNLgR6osk2E56ekp"' \

--form 'client_secret="6urNLgR6osk2E56ekp"' \

--form 'grant_type="refresh_token"' \

--form 'refresh_token="TZ9tzVwE_VLoJxALUSw4A4A0Nj7SLSWXCc69U9rvNmSnqR8Hbz-1m4uHebJWsAK0sa7SDIR4SNXOB3iaM0p1bH_8EBrljoBApQgdYi1uYzcVwYq55OVV2RUHN2BJwfSr"'

  1. 响应
  • 正常 [200]

{

    "access_token": "YnVdTXl0MhslsrOjiz1ffSixvPnWCN-XS-UBlkS89daZbd_TvXtSSo_ODuFVWPWw1KsO5WQykVPjwSe_Kreo8ngIP9DglaXJMbYJJu4Wa6_geOINj5ksmnbfb6pHrQHr",

    "refresh_token": "TZ9tzVwE_VLoJxALUSw4A4A0Nj7SLSWXCc69U9rvNmSnqR8Hbz-1m4uHebJWsAK0sa7SDIR4SNXOB3iaM0p1bH_8EBrljoBApQgdYi1uYzcVwYq55OVV2RUHN2BJwfSr",

    "scope": "openid profile",

    "id_token": "eyJraWQiOiJzb3MtZWNjLWtpZDEiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJ1bml0eSIsImF1ZCI6IjZ1ck5MZ1I2b3NrMkU1NmVrcCIsInVwZGF0ZWRfYXQiOjAsImF6cCI6IjZ1ck5MZ1I2b3NrMkU1NmVrcCIsImF1dGhfdGltZSI6MTY5NzcwNzM1NCwiaXNzIjoiaHR0cDovLzEyNy4wLjAuMTo4MDgwIiwibmlja25hbWUiOiIiLCJleHAiOjE2OTc3MjQyNjMsImlhdCI6MTY5NzcyMjQ2MywianRpIjoiMDc4OTc4MTUxNzEwNTgwNDE2ODY0NzgxMDQ1OTM5MDYiLCJzaWQiOiJ1d3A3bnlGcnB2U21aaVBLaEJ1ZVJUVl9xVEpiQ3pmMDJOZjBBNkY3WWtJIn0.j0KVv7bAi85zbX-0wvWe83n_CQdmJLGrHJNFwF5jA1-wa8QzaSwJbznpjbHLGTv-UbI2YeHLn8N5iGXDarbC9Q",

    "token_type": "Bearer",

    "expires_in": 3599

}

  • 异常 [401]

{

    "error": "invalid_client"

}

2.6检查token (/oauth2/introspect) public

校验, 检查token的有效性

  1. 求URI: /oauth2/introspect POST
  2. 请求参数说明:

参数名

参数值

必须?

备注

client_id

{client_id}

client_secret

{client_secret}

token

{token}

token可以是access_token, refresh_token 或 id_token

  1. 请求示例:

curl --location 'http://localhost:8080/oauth2/introspect' \

--header 'Content-Type: application/json' \

--form 'client_id="6urNLgR6osk2E56ekp"' \

--form 'client_secret="6urNLgR6osk2E56ekp"' \

--form 'token="GaHu88XEEAz41xMHfDk05bg9uSJ5Go1RF6jOe5eX7OhHD_52NK_fuwvVWq_dTRIhK8WR9SnCAtBBc0fVsOyGgz8-MhmVTG-dcDi6QtGQQtYxwmGrD-fOhpmePdUv6pwV"'

  1. 响应
  • 正常 [200]

{

    "active": true,

    "sub": "admin",

    "aud": [

        "6urNLgR6osk2E56ekp"

    ],

    "nbf": 1697721873,

    "scope": "openid profile",

    "iss": "http://127.0.0.1:8080",

    "exp": 1697725474,

    "iat": 1697721874,

    "jti": "a1aa8f82-c885-45b3-a469-c2f595e8f12d",

    "client_id": "6urNLgR6osk2E56ekp",

    "token_type": "Bearer"

}

根据不同类型的token响应结果不相同; active=true表示token为有效的

  • 异常 [200]

{

    "active": false

}

2.7 OIDC /userinfo 获取用户信息

客户端带上access_token获取用户信息

  1. 请求URI: /userinfo GET
  2. 请求示例:

curl --location 'http://localhost:8080/userinfo' \

--header 'Content-Type: application/json' \

--header 'Authorization: Bearer eyJraWQiOiJzb3MtcnNhLWtpZDIiLCJhbGciOiJSUzI1NiJ9.eyJzdWI...'

  1. 响应
  • 正常 [200]

{

    "sub": "unity",

    "updated_at": 0,

    "nickname": ""

}

  • 具体有哪些属性值由scope范围来决定
  • 异常 [401]

3.小程序接口

登录凭证校验 /minapp/code2session

通过 wx.login 接口获得临时登录凭证 code 后调用此接口,参考https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html

接口返回微信登录信息和统一登录平台的accessToken

获取小程序手机号 /minapp/getuserphonenumber

参考 https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html

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

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

相关文章

CV计算机视觉每日开源代码Paper with code速览-2023.11.27

点击CV计算机视觉,关注更多CV干货 论文已打包,点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【图像分割】SEGIC: Unleashing the Emergent Correspondence for In-Context Segmentation 论文地址:https://arxiv.org//pdf/2…

SpringCloudAlibaba微服务 【实用篇】| Nacos配置管理

目录 一:Nacos配置管理 1. 统一配置管理 2. 配置热更新 3. 配置共享 4. 搭建Nacos集群 tips:前些天突然发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,感兴趣的同学可以进…

nginx: [alert] could not open error log file

先把cmd的报错信息粘出来 nginx: [alert] could not open error log file: CreateFile() “logs/error.log” failed (3: The system cannot find the path specified) 2023/11/29 11:27:37 [emerg] 5040#18772: CreateDirectory() “D:\enviroment\nginx-1.24.0\conf/temp/cli…

c#把bitmap格式转换为其他格式图片

增加引用命名空间 using System.Drawing.Imaging; 打开对话框的方式读入bmp格式图片,转换为其他格式。 也可以直接传入图片名称。 OpenFileDialog ofd new OpenFileDialog();ofd.Title "打开对话框";ofd.InitialDirectory "D:/";ofd.Filt…

Python基础语法之学习占位符

Python基础语法之学习占位符 一、代码二、效果 一、代码 name "张三" sex "男" age 10 money 12.5# 通过占位符完成拼接 print("姓名:%s" % name) print("姓名:%s,性别:%s" % (name, sex))text…

nexus制品库的介绍及详细部署使用

一、nexus 介绍 Nexus 是一个强大的仓库管理工具,用于管理和分发 Maven、npm、Docker 等软件包。它提供了一个集中的存储库,用于存储和管理软件包,并提供了版本控制、访问控制、构建和部署等功能。 Nexus 可以帮助开发团队提高软件包管理的效…

直流负载与交流负载的作用

直流负载和交流负载都是用来消耗电能的装置或设备,它们的作用是将电能转化为其他形式的能量,以满足特定的需求。直流负载主要用于直流电路中,例如直流电源、电池等。它们可以将直流电能转化为热能、光能、机械能等。直流负载在很多领域都有广…

JavaScript图片处理大揭秘!掌握文件流处理方法

说在前面 💻作为一名前端开发,我们平时也少不了对文件流数据进行处理,今天简单整理一下日常开发中比较常见的一些处理文件流的场景及处理方法,希望可以帮助到大家,挤出多一点的摸鱼学习时间。 常见场景 一、input框上…

uniapp + electron 打包项目

参考文献 1、控制台安装electron和electron打包工具electron-packager npm install electron -g npm install electron-packager -g2、manifest.json修改 运行的基础路径修改为:./ 不然打包出来会出现白屏,读取不到,因为打包出来的h5默认加…

强大的Kubernetes工具的完整指南

在容器化应用程序编排方面,Kubernetes是市场的领导者。它允许用户在多主机环境中管理容器,提供工作负载分配和网络处理。 此外,它还提供了许多在DevOps过程中至关重要的特性,例如自动扩展、自动修复和负载平衡。这些功能解释了Kub…

xcconfig(环境变量) 的使用

xcconfig(环境变量) 的使用 文章目录 xcconfig(环境变量) 的使用一、上手使用1、添加 xcconfig 文件2、在文件中添加数据3、将文件配置到工程中4、使用环境变量5、使用 Pod 的项目 二、语法1、注释:2、包含语句&#x…

C语言之“可变参数<stdarg.h>”

目录 前言 stdarg.h头文件 实例:遍历并求和所有传递给sum函数的额外实际参数 前言 有时我们会希望函数带有可变数量的参数就像printf(cosnt char* format ...)和scanf(cosnt char* format ...)那样除了有一个参数 …

ArkTS-文本滑动选择器弹窗

文本滑动选择器弹窗 根据指定的选择范围创建文本选择器,展示在弹窗上。 示例 Entry Component struct TextPickerDialogExample {State select: number 2private fruits: string[] [苹果, 香蕉, 橘子, 梨儿, 桃儿]build() {Row() {Column() {Text(当前选择为&…

windows系统bat脚本命令总结之reg命令

前言 做了一段时间的bat脚本开发,bat脚本中有各种各样的命令跟传统的编程逻辑完全不同,本专栏会讲解下各种各式的命令使用方法。 本篇文章讲解的是windows系统注册表操作命令"reg"。 reg命令简介 “reg” 是 Windows 操作系统中的一个命令行工…

关于前端学习的思考-浮动元素和块级元素的关系

先摆关系:浮动元素嵌套块级元素,浮动元素和块级元素是上下关系。 1、浮动元素为父盒子,块级元素为子盒子。 父盒子为浮动元素,子盒子不会继承。如图floatnone; 摆结论:子盒子为行内元素,行内块…

智能优化算法应用:基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.群居蜘蛛算法4.实验参数设定5.算法结果6.参考…

excel 计算断面水质等级

在工作中遇到根据水质监测结果要判断断面等级。写了下面的公式: 因子标准值 limits {COD: [15,15, 20, 15,20],氨氮: [0.15, 0.5, 1, 1.5, 2.0],总磷: [0.02, 0.1, 0.2, 0.3, 0.4] } excel公式: IFS(MAX(IF(M2>20,1,0), IF(N2>2,1,0), IF(O2&g…

夜莺项目发布 v6.4.0 版本,新增全局宏变量功能

大家好,夜莺项目发布 v6.4.0 版本,新增全局宏变量功能,本文为大家简要介绍一下相关更新内容。 全局宏变量功能 像 SMTP 的配置中密码类型的信息,之前都是以明文的方式在页面展示,夜莺支持全局宏变量之后,可…

SpringMvc集成开源流量监控、限流、熔断降级、负载保护组件Sentinel | 京东云技术团队

前言:作者查阅了Sentinel官网、51CTO、CSDN、码农家园、博客园等很多技术文章都没有很准确的springmvc集成Sentinel的示例,因此整理了本文,主要介绍SpringMvc集成Sentinel SpringMvc集成Sentinel 一、Sentinel 介绍 随着微服务的流行&…

SpringBoot Bean解析

Bean解析 IOC介绍 松耦合灵活性可维护 注解方式配置Bean 实现方式1: Component声明,直接类上进行添加注解, 同时保证包扫描能扫到即可实现方式2: 配置类中使用Bean Configuration public class BeanConfiguration implements SuperConfiguration{Bean("dog")Ani…