一、说明

本文主要是给大家介绍 OIDC 的核心概念以及如何通过对 Spring Security 的授权码模式进行扩展来实现 OIDC 的单点登录。

OIDC 是 OpenID Connect 的简称,OIDC=(Identity, Authentication) + OAuth 2.0。它在 OAuth2 上构建了一个身份层,是一个基于 OAuth2 协议的身份认证标准协议。我们都知道 OAuth2 是一个授权协议,它无法提供完善的身份认证功能,OIDC 使用 OAuth2 的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端,且完全兼容 OAuth2。

PS:理解 OIDC 的前提是需要理解 OAuth2,如果对 OAuth2 的单点登录的原理和流程还不太了解的可以看我之前的文章《Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

二、OIDC核心概念

OAuth2 提供了 Access Token 来解决授权第三方 客户端 访问受保护资源的问题;OIDC 在这个基础上提供了 ID Token 来解决第三方客户端标识用户身份认证的问题。OIDC 的核心在于 OAuth2 的授权流程中,一并提供用户的身份认证信息 ID Token 给到第三方 客户端ID Token 使用 JWT 格式来包装。

OIDC协议授权返回示例

{
"resp_code": 200,
"resp_msg": "ok",
"datas": {
"access_token": "d1186597-aeb4-4214-b176-08ec09b1f1ed",
"token_type": "bearer",
"refresh_token": "37fd65d8-f017-4b5a-9975-22b3067fb30b",
"expires_in": 3599,
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vemx0MjAwMC5jbiIsImlhdCI6MTYyMTY5NjU4MjYxNSwiZXhwIjoxNjIxNjk2NjQyNjE1LCJzdWIiOiIxIiwibmFtZSI6IueuoeeQhuWRmCIsImxvZ2luX25hbWUiOiJhZG1pbiIsInBpY3R1cmUiOiJodHRwOi8vcGtxdG1uMHAxLmJrdC5jbG91ZGRuLmNvbS_lpLTlg48ucG5nIiwiYXVkIjoiYXBwIiwibm9uY2UiOiJ0NDlicGcifQ.UhsJpHYMWRmny45K0CygXeaASFawqtP2-zgWPDnn0XiBJ6yeiNo5QAwerjf9NFP1YBxuobRUzzhkzRikWGwzramNG9na0NPi4yUQjPNZitX1JzlIA8XSq4LNsuPKO7hS1ALqqiAEHS3oUqKAsjuE-ygt0fN9iVj2LyL3-GFpql0UAFIHhew_J7yIpR14snSh3iLVTmSWNknGu2boDvyO5LWonnUjkNB3XSGD0ukI3UEEFXBJWyOD9rPqfTDOy0sTG_-9wjDEV0WbtJf4FyfO3hPu--bwtM_U0kxRbfLnOujFXyVUStiCKG45wg7iI4Du2lamPJoJCplwjHKWdPc6Zw"
}
}

可以看到与普通的 OAuth2 相比返回的信息中除了有 access_token 之外还多出了 id_token 属性。

三、什么是 ID Token

ID Token 是一个安全令牌,由授权服务器提供的包含用户信息的 JWT 格式的数据结构,得益于 JWT(JSON Web Token)的自包含性,紧凑性以及防篡改机制,使得 ID Token 可以安全的传递给第三方客户端程序并且容易被验证。

id_token包含以下内容

{
"iss": "http://zlt2000.cn",
"iat": 1621696582615,
"exp": 1621696642615,
"sub": "1",
"name": "管理员",
"login_name": "admin",
"picture": "http://xxx/头像.png",
"aud": "app",
"nonce": "t49bpg"
}
  • iss:令牌颁发者
  • iat:令牌颁发时间戳
  • exp:令牌过期时间戳
  • sub:用户id
  • name:用户姓名
  • login_name:用户登录名
  • picture:用户头像
  • aud:令牌接收者,OAuth应用ID
  • nonce:随机字符串,用来防止重放攻击

3.1. 与 JWT 的 Access Token 区别

是否可以直接使用 JWT 方式的 Access Token 并在 Payload 中加入用户信息来代替 ID Token 呢?

虽然在 Access Token 中可以加入用户的信息,并且是防篡改的,但是用户的每次请求都需要携带着 Access Token,这样不但增加了带宽,而且很容易泄露用户的信息。

3.2. 与 UserInfo 端点的区别

通常 OIDC 协议都需要另外提供了一个 Get /userinfo 的 Endpoint,需要通过 Access Token 调用该 Endpoint 来获取详细的用户信息,这个方法和 ID Token 同样都可以获取用户信息,那两者有什么区别呢?

相比较于 Get /userinfo 的接口使用 ID Token 可以减少远程 API 调用的额外开销;使用那个主要是看 需求,当你只需要获取用户的基本信息直接使用 ID Token 就可以了,并不需要每次都通过 Access Token 去调用 Get /userinfo 获取详细的用户信息。

四、OIDC 单点登录流程

下面我们看一个 OIDC 协议常用的场景,就是具有 独立用户体系 系统间的单点登录,意思指的是用户数据并不是统一共用的,而是每个系统都拥有自己独立的用户数据,所以流程最后增加了一步 自动注册用户

大部分的流程与 OAuth2 的授权码模式相同这里就不多讲述了,其中下面两个步骤需要说明一下:

  • 解析 ID Token 的公钥可以是预先提供给第三方系统也可以是提供接口获取。
  • 自动注册用户 指的是第一次单点登录的时候,由于用户信息不存在需要在本系统中生成该用户数据;例如你从未在 CSDN 中注册也可以使用微信来登录该网站。

五、Spring Security 实现

先说一下扩展最终的目标是需要达到以下效果:

  • 授权码模式:/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code
  • OIDC 模式:/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type=code id_token

目标是要通过在 response_type 中的传值来控制是否使用 OIDC 模式,如果使用则在 response_type 中增加 id_token 的值。

由于需要在 OAuth2 返回的内容中添加 ID Token 属性,所以实现这个扩展的关键就是需要通过 Security 的 TokenEnhancer 来为 Token 添加自定义字段;

定义 TokenEnhancer 的 Bean 来扩展 Token:

通过授权的 response_type 参数来判断是否需要生成 id_token。

生成 ID Token 的 JWT:

PS:上面只列出了部分关键代码,完整代码请通过下面的 demo 地址去下载。

六、完整的 demo 下载地址

https://gitee.com/zlt2000/microservices-platform/tree/master/zlt-demo/sso-demo/oidc-sso

扫码关注有惊喜!

如何基于Security实现OIDC单点登录?的更多相关文章

  1. Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...

  2. Spring Security OAuth2 SSO 单点登录

    基于 Spring Security OAuth2 SSO 单点登录系统 SSO简介 单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自 ...

  3. 【SpringSecurityOAuth2】源码分析@EnableOAuth2Sso在Spring Security OAuth2 SSO单点登录场景下的作用

    目录 一.从Spring Security OAuth2官方文档了解@EnableOAuth2Sso作用 二.源码分析@EnableOAuth2Sso作用 @EnableOAuth2Client OA ...

  4. 前后端分离基于Oauth2的SSO单点登录怎样做?

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼:本文主要介绍跨域间的 前后端分离 项目怎样实现单点登录,并且与 非前后端分离 的差 ...

  5. .NET基于Redis缓存实现单点登录SSO的解决方案[转]

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  6. .NET基于Redis缓存实现单点登录SSO的解决方案

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  7. SSO 基于Cookie+fliter实现单点登录(SSO):工作原理

    SSO的概念: 单点登录SSO(Single Sign-On)是身份管理中的一部分. SSO的一种较为通俗的定义是:SSO是指訪问同一server不同应用中的受保护资源的同一用户,仅仅须要登录一次,即 ...

  8. SSO 基于Cookie+fliter实现单点登录 实例解析(一)

    接上文,SSO的理论讲解,接下来实践实践! 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/").即Tomcat的目录下都有效 2.设置 ...

  9. springboot+security+JWT实现单点登录

    本次整合实现的目标:1.SSO单点登录2.基于角色和spring security注解的权限控制. 整合过程如下: 1.使用maven构建项目,加入先关依赖,pom.xml如下: <?xml v ...

随机推荐

  1. Quartz任务调度(2)CronTrigger定制个性化调度方案

    Cron表达式 1. 时间字段与基本格式 Cron表达式有6或7个空格分割的时间字段组成: 位置 时间域名 允许值 允许的特殊字符 1 秒 0-59 ,-*/ 2 分支 0-59 ,-*?/ 3 小时 ...

  2. Navicate 连接阿里云MySQL(两种方式及原理讲解)

    Navicate 连接阿里云(两种方式及原理讲解) 一.直连方式(通过3306端口) 1.概述 2. 环境准备 3.操作及讲解 二.使用SSH通道 1.概述 2.环境准备 3.操作及讲解 如果对你有帮 ...

  3. linux(5)----------防火墙的配置

    1.安装:    yum install firewalld 2.启动:    service firewalld start 3.检查状态:        service firewalld sta ...

  4. Spring之JDBC Template

    时间:2017-2-5 18:16 --Spring对不同持久化技术的支持Spring为各种支持的持久化技术都提供了简单操作的模板和回调.ORM持久化技术:    JDBC:        org.s ...

  5. Ubuntu18.04 + NVidia显卡 + Anaconda3 + Tensorflow-GPU 安装、配置、测试 (无需手动安装CUDA)

    其中其决定作用的是这篇文章  https://www.pugetsystems.com/labs/hpc/Install-TensorFlow-with-GPU-Support-the-Easy-Wa ...

  6. Learning ROS: Roslaunch tips for large projects

    Design tip: Top-level launch files should be short, and consist of include's to other files correspo ...

  7. Nginx反向代理之巨坑underscores_in_headers

    一.背景 因为项目需求,在做Windows的相关的事情:基本架构就是Nginx--> Nginx --> IIS,在Linux机器上通过Nginx做反向代理到Windows的IIS:然后遇 ...

  8. 关于Cloudfront能否接入NLB的讨论

    之前讨论过四层应用 是无法通过七层负载负载均衡器转发流量的,因为ALB监听的是Http/s协议,TCP/UDP的请求到了ALB无法识别,ALB在第七层做判断,数据包只有四层,会无法判断转发的目标.相反 ...

  9. MyBatis学习总结(四)——字段名与实体类属性名不相同的冲突的解决

    表中的字段名和表对应实体类的属性名称不一定都是完全相同的,这种情况下的如何解决字段名与实体类属性名不相同的冲突.如下所示: 一.准备演示需要使用的表和数据 CREATE TABLE my_user( ...

  10. VS Code 搭建stm32开发环境

    MCU免费开发环境 一般芯片厂家会提供各种开发IDE方案,通常其中就包括其自家的集成IDE,如: 意法半导体 STM32CubeIDE NXP Codewarrior TI CCS 另外也可以用ecl ...