Files
2026-07-28 22:30:20 +08:00

370 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 研发云互联互通规范系统接入技术规范(用户认证和资产授权)(试行稿)
> 脱敏整理版:已移除编制人员、联系人和联系方式,并合并无意义硬换行。技术条款、章节和示例以原始 DOCX 为争议核验依据。
研发云平台互联互通规范
系统接入技术规范(用户认证和资产授权)
中国电信股份有限公司研究院研发云平台运营中心
## 2025 年 5 月
1
版本变更历史
2
## 1 文档说明
### 1.1 编制说明
### 1.2 适用范围
### 1.3 起草单位
### 1.4 解释权
### 1.5 版权
### 1.6 名词解释
## 2 概述
1
在集团研发生态系统持续构建过程中,研发云平台与外部系统进行集成,以实现数据共享、功能协同或流程自动化。这里外部系统是指项目在研发过程中需要使用的外部系统,不包括与项目完成后需要部署的生产系统的对接。研发云平台支持天翼认证、云认证及研发云账号密码登录三种方式的单点登录。
1)天翼认证
外部系统与研发云的认证对接基于天翼认证进行对接单点登录,对接规范按照天翼认证认证系统要求
2)云认证
外部系统与研发云的认证对接基于云认证进行对接单点登录,对接规范按照云认证认证系统要求
3)研发云认证
外部系统通过 Oauth 协议与研发云对接认证。
以上三种认证方式,均可在研发云上为外部系统提供跳转入口实现简单的单点登录跳转。其中研发云认证可基于外部系统的需求,提供界面集成、资产授权的更深入的对接和整合。本文的主要提供研发云认证的 OAuth 协议及系统集成、资产授权的相关技术说明。
## 3 OAuth 鉴权服务
OAuth 鉴权服务,名为 OAuthServer,是本平台中专门用于 OAuth 协议鉴权的服务。本章介绍 OAuth 服务的设计要点以及接口定义。本服务支持获取研发云代码仓库及项目制品库资产的访问令牌。
### 3.1 协议流程
2
OAuthServer 连同相关的前端授权页面配合实现了整个平台中对 OAuth 鉴权的协议栈,其在整个平台中的角色以及和外部应用的关系如下图所示:
OAuthServer 服务按照 RFC 6749 协议标准,实现了 OAuth2.0 的四种鉴权模式,分别为:授权码(authorization-code)、隐藏式(implicit)、密码式(password)、客户端凭证(client credentials)。在上述 4 种 OAuth2.0 的认证鉴权模式中,授权码(authorization-code)、隐藏式(implicit)这两种模式需要本平台提供前端页面配合实现。OAuthServer 服务通过 client_id 和 client_secret 字段值对申请 OAuth 认证的外部应用进行身份检查。
### 3.2 Token 类型和生成
按照 RFC6749 规范的规定,OAuthServer 支持 access token 和 id-token 两种token。Access token 是发送到外部应用的,用于访问资源服务的鉴权token,id-token对 部 分 用 户 进 行 JWT 加 密 后 的 用 户 信 息 内 容 。 OAuthServer 服 务 会 在/oauth/access_token 的接口处理中,同时生成 access token 和 id_token,并返回给3
外部应用。对于 access token,根据 RFC6750OAuthServer 服务支持 bearer 类型的 token。 OAuthServer 对 token 的生成采用 jwt 协议对令牌内容进行签名,从而得到生成的 token 字串。Access token 所签名的内容包括:
OAuthServer 在 tokengenerator 文件的 GenerateToken 方法中实现 access token的生成,将上述表格的内容使用 client_id 对应的外部应用的 client_secret 对这些内容进行签名,从而得到 access token 字串。
另外根据 RFC7519 进行jwt 安全加密。Access token 所签名的内容包括:
### 3.3 接口定义
#### 3.3.1 前端跳转地址
1Authorize 请求
接口说明请求 AuthorizationCode 或者隐藏模式下请求 Token 4
接口方法Get接口地址http://server:port/login/oauth/authorize消息体
返回响应HTTP 状态码 : 301
重定向访问5
重定向地址:Authorize 请求中的 redirect_uri 地址HTTP 结构:
2)参数示例
重定向访问GET https://www.srdcloud.cn/login/oauth/authorize Parameters:response_type : "code",client_id: "2423402bb71a1t5k7hbwssd2", state"string",redirect_uri: "https://test.com/auth"scope: "projectId:12"
重定向返回GET https://test.com/auth Parameters:code: "HgC4EfdqVC4ZiOPSjk", state: "string",
#### 3.3.2 后端接口
6
##### 3.3.2.1 请求 Token
1)接口说明
请求生成 access token。本接口向外部应用以及本平台前端授权页面开放,用于向本平台获取 access token。
这个接口是 OAuth2.0 的 4 种模式统一的接口,兼容 4 种模式的请求 access token 操作,根据每种模式的不同,所携带的请求参数也不同。
接口方法Post接口地址http://server:port/api/usercenterbackend/login/oauth/access_token消息体
7
返回响应
1)如无redirect_url,或者出现其他错误无法重定向,直接返回响应HTTP 状态码 : 200
响应编码方式:application/x-www-form-urlencoded; charset=utf-8正常响应结构:
id token 包含:8
asset 结构:
9
错误响应结构:
2)参数示例
入参POST https://www.srdcloud.cn/api/usercenterbackend/login/oauth/access_token Request Body (application/json):
{
"grant_type": "authorization_code",
"client_id": "2423402bb71a1t5k7hbwssd2",
"client_secret": "220943643b24uUOYMYWhsWh012osSJI7lVavs8bqmDUQ4Az" , "code":"HgC4EfdqVC4ZiOPSjk"
}
返回示例POST https://www.srdcloud.cn/api/usercenterbackend/login/oauth/access_token Response Body (application/x-www-form-urlencoded):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiI yNDIzNDAyYmI3MWExdDVrN2hid3NzZDIiLCJleHAiOjE3MzQxNTMyODMsIm lzcyI6IjEwIiwic2NvcGUiOiJwcm9qZWN0SWQ6MTIiLCJ0b2tlblR5cGUiOiJiZWFy ZXIifQ.bEkdU4aqq_aabjSE9F0STJD2ytFwg8J2JJnhBA1PR9Q",
"expires_in": "86400",
10
"id_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZF90b2tlbiI6eyJsb2dp biI6InRlc3RVc2VyIiwiZW1haWwiOiJ0ZXN0VXNlckBjaGluYXRlbGVjb20uY24iL CJhdXRoX3Rva2VuIjoiZGRiNzJkY2ItNDE5NC00ZmNhLTgyNDUtMGM5NGE0N ThhYzdiIiwiYXNzZXRzIjpbeyJhc3NldF9uYW1lIjoidGVzdDIwMjQwNjE3YS9iIiwi YXNzZXRfdHlwZSI6IkNvZGVSZXBvc2l0b3J5IiwiYXNzZXRfYXV0aCI6Ik1hbm FnZXIiLCJhc3NldF91cmwiOiJodHRwczovL3R1dzFAZGV2LWNvZGUuc3JkY2xv dWQuY24vYS90ZXN0MjAyNDA2MTdhL2IiLCJhc3NldF90b2tlbiI6ImppWUs5dHl kSTZZOFlGZkFpYVZ4RnlaYmRzTU9WTnUzOUxQVCtDNCtTWiIsImV4cGlyZX NfaW4iOiIxNzM0MDgyMDczIn0seyJhc3NldF9uYW1lIjoidGVzdDIwMjQwNjE3Y S9jIiwiYXNzZXRfdHlwZSI6IkNvZGVSZXBvc2l0b3J5IiwiYXNzZXRfYXV0aCI6I k1hbmFnZXIiLCJhc3NldF91cmwiOiJodHRwczovL3R1dzFAZGV2LWNvZGUuc3J kY2xvdWQuY24vYS90ZXN0MjAyNDA2MTdhL2MiLCJhc3NldF90b2tlbiI6Impp
WUs5dHlkSTZZOFlGZkFpYVZ4RnlaYmRzTU9WTnUzOUxQVCtDNCtTWiIsImV 4cGlyZXNfaW4iOiIxNzM0MDgyMDczIn0seyJhc3NldF9uYW1lIjoidGVzdDIwMjQ wNjE3YS9hYSIsImFzc2V0X3R5cGUiOiJDb2RlUmVwb3NpdG9yeSIsImFzc2V0X2 F1dGgiOiJNYW5hZ2VyIiwiYXNzZXRfdXJsIjoiaHR0cHM6Ly90dXcxQGRldi1jb2 RlLnNyZGNsb3VkLmNuL2EvdGVzdDIwMjQwNjE3YS9hYSIsImFzc2V0X3Rva2 VuIjoiamlZSzl0eWRJNlk4WUZmQWlhVnhGeVpiZHNNT1ZOdTM5TFBUK0M0K 1NaIiwiZXhwaXJlc19pbiI6IjE3MzQwODIwNzMifSx7ImFzc2V0X25hbWUiOiJ0ZX N0MjAyNDA2MTdhLXJlbGVhc2UtY29jb2Fwb2RzLWxvY2FsIiwiYXNzZXRfdHl wZSI6IkxvY2FsQXJ0aWZhY3RSZXBvc2l0b3J5IiwiYXNzZXRfYXV0aCI6ImFkb WluIiwiYXNzZXRfdXJsIjoiaHR0cHM6Ly9kZXYtc3JkYXJ0LnNyZGNsb3VkLmN uL2NvY29hcG9kcy90ZXN0MjAyNDA2MTdhL3Rlc3QyMDI0MDYxN2EtcmVsZ WFzZS1jb2NvYXBvZHMtbG9jYWwiLCJhc3NldF90b2tlbiI6ImI4ODZmOTJhN2M 0ZWQyMTU2YTk0MWMzZTQ2NzFlYTYzIiwiZXhwaXJlc19pbiI6IjE3MzQwODI wNzMifSx7ImFzc2V0X25hbWUiOiJ0ZXN0MjAyNDA2MTdhLXNuYXBzaG90L WNvY29hcG9kcy1sb2NhbCIsImFzc2V0X3R5cGUiOiJMb2NhbEFydGlmYWN0U mVwb3NpdG9yeSIsImFzc2V0X2F1dGgiOiJhZG1pbiIsImFzc2V0X3VybCI6Imh0d HBzOi8vZGV2LXNyZGFydC5zcmRjbG91ZC5jbi9jb2NvYXBvZHMvdGVzdDIwM 11
jQwNjE3YS90ZXN0MjAyNDA2MTdhLXNuYXBzaG90LWNvY29hcG9kcy1sb2N hbCIsImFzc2V0X3Rva2VuIjoiYjg4NmY5MmE3YzRlZDIxNTZhOTQxYzNlNDY3 MWVhNjMiLCJleHBpcmVzX2luIjoiMTczNDA4MjA3MyJ9XSwicHJvamVjdF9uY W1lIjoiYXBhYXNUZXN0UHJvamVjdCIsInByb2plY3Rfcm9sZSI6IjEifX0.RAbWb GiCA3PSjrjP36XYdS_u4Mh5gmN9Lmoj1-FZDig" ,
"token_type":"bearer"
}
jwt 加密头域
{
"alg": "HS256",
"typ": "JWT"
}
Id—token 解析内容
{
"id_token": {
"login": "testUser",
"email": "[邮箱已脱敏]",
"auth_token": "ddb72dcb-4194-4fca-8245-0c94a458ac7b",
"assets": [
{
"asset_name": "test20240617a/b",
"asset_type": "CodeRepository",
"asset_auth": "Manager",
"asset_url": "https://[邮箱已脱敏]/a/test20240617a/b",
"asset_token": "jiYK9tydI6Y8YFfAiaVxFyZbdsMOVNu39LPT+C4+SZ", "expires_in": "1734082073"
},
12
{
"asset_name": "test20240617a/c",
"asset_type": "CodeRepository",
"asset_auth": "Manager",
"asset_url": "https://[邮箱已脱敏]/a/test20240617a/c",
"asset_token": "jiYK9tydI6Y8YFfAiaVxFyZbdsMOVNu39LPT+C4+SZ", "expires_in": "1734082073"
},
{
"asset_name": "test20240617a/aa",
"asset_type": "CodeRepository",
"asset_auth": "Manager",
"asset_url": "https://[邮箱已脱敏]/a/test20240617a/aa",
"asset_token": "jiYK9tydI6Y8YFfAiaVxFyZbdsMOVNu39LPT+C4+SZ", "expires_in": "1734082073"
},
{
"asset_name": "test20240617a-release-cocoapods-local",
"asset_type": "LocalArtifactRepository",
"asset_auth": "admin",
"asset_url": "https://dev-
srdart.srdcloud.cn/cocoapods/test20240617a/test20240617a-release-cocoapods-local",
"asset_token": "b886f92a7c4ed2156a941c3e4671ea63",
"expires_in": "1734082073"
},
{
"asset_name": "test20240617a-snapshot-cocoapods-local",
"asset_type": "LocalArtifactRepository",
"asset_auth": "admin",
13
"asset_url": "https://dev-
srdart.srdcloud.cn/cocoapods/test20240617a/test20240617a-snapshot-cocoapods-local",
"asset_token": "b886f92a7c4ed2156a941c3e4671ea63", "expires_in": "1734082073"
}
],
"project_name": "apaasTestProject",
"project_role": "1"
}
}
##### 3.2.2.2 请求用户信息
1)接口说明
使用 access_token 获取用户信息接口方法GET接口地址http://server:port/api/usercenterbackend/user头部Authorizationbearer [access_token]返回响应HTTP 状态码: 200响应编码方式:application/json; charset=utf-8
14
错误响应结构:HTTP 状态码: 401响应编码方式:application/json; charset=utf-8
2)参数示例
GET https://www.srdcloud.cn/api/usercenterbackend/user Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQi OiIyNDIzNDAyYmI3MWExdDVrN2hid3NzZDIiLCJleHAiOjE3MzQxNTQwNzMs ImlzcyI6IjEwIiwic2NvcGUiOiJwcm9qZWN0SWQ6MTIiLCJ0b2tlblR5cGUiOiJiZW FyZ5XIifQ.MryoXA18ov_gAGv8plY7BMQCm52bGDvyIVoShk1m7984123 Content-Type: application/json
返回POST https://www.srdcloud.cn/api/usercenterbackend/user Response Body (application/json):
{
"id":10,
"login":"testUser",
"user_key":"",
15
"company":"中国电信集团",
"email":"[邮箱已脱敏]", "mobile":"[手机号已脱敏]",
"created_at":"2024-02-29 14:46:35", "updated_at":"2024-11-28 09:22:44" }
## 4 系统集成方式
在单点登录的基础上,提供 2 种集成方式:系统跳转和界面集成
### 4.1 系统跳转
用户登录研发云后,点击外部系统入口跳转进入相应系统。对接单点认证后,与研发云门户产品经理确认系统跳转菜单位置,经过领导确认后排期上线。
### 4.2 界面集成
在研发云系统内嵌入外部系统功能页面,用户登录研发云后,在研发云的同一界面下完成相应的功能流程,无跳转体验。
页面集成通过 iframe 嵌入的方式集成,研发云与外部系统共同完成集成产品设置,包括菜单设置等。产品确认后研发云门户前端配置应用子系统嵌入外部系统链接。
页面集成对于外部系统的要求如下:■ 由外部系统提供对应的前台菜单集合和链接
16
■ 由外部平台提出打开对应菜单链接的其他要求,例如替换链接中的某些参数、新增某些参数/标识等■ 外部平台和研发云页面之间的通信要求,统一使用 postMessage 进行页面之间的通信。
具体格式如下window.postMessage({valueType: "xxx", // 双方约定事件名称data: {}, // 具体参数
}, "*");
## 5 用户访问对接系统资源
用户使用对接系统资源,根据对接系统分配资源的方式,分为 2 种:● 按用户:按用户维度访问对接系统资源。用户登录后即可使用对接系统分配给用户的资源;● 按项目:对接系统按项目分配资源。这种情况下,需要增加额外的步骤使用对接系统资源:■ 同步研发云项目到对接系统。需要具备相应管理权限的用户在研发云平台将研发云平台项目同步到对接系统(在对接系统新建或映射)■ 同步用户授权到对接系统。需要具备相应管理权限的用户在研发云平台将研发云用户授权信息同步到对接系统
以上需要对接系统提供同步项目及授权用户的接口,同时研发云需要进行项目和授权用户同步功能的开发。
### 5.1 对接系统访问研发云资源
17
在用户使用对接系统功能时,可能需要将对接系统的产出,例如代码、制品等资产同步到研发云系统,主要涉研发云以下的资源:● 代码库● 制品库● 组件广场
1)手工配置资源访问权限
用户在对接系统上手工配置资源的访问权限,例如用户名和密码等。
这种方式存在以下问题:
● 体验不佳,用户需要手工配置资源地址、密码等;密码变更时,需要在所有相关系统上修改;● 安全性不佳,资源地址和密码是静态配置,在用户登出系统后该配置仍然长期有效;● 如果采用 API 方式访问资源,存在访问范围过大的问题,外部系统可通过 API 获取用户所有的资源信息
2)使用 OAuth 授权方式访问资源
利用在用户认证授权过程中获取的 Token 访问研发云资源。
研发云在生成 access/id token 的时候,将对资源访问的动态密码放到 ID token (JWT)的 payload 里。对接系统接收到 token 后,解析出token 中的动态密码。后续使用动态密码访问资源系统。具体过程如下:
18
● 用户授权后,用户中心根据授权情况去各个资源中心获取动态密码;各资源中心提供获取动态密码的接口;● 用户中心将获取的动态密码编码到 ID Token(JWT 格式)的 payload 中,并返回给对接系统;● 对接系统对 ID Token 进行解析,取出动态密码,用于后续访问研发云资源;资源中心负责对其颁发的动态密码的访问权限及生命周期的管理。动态密码的初始有效期由各资源中心确定,同时,各个资源中心按自身的产品规划,可提供延长、终止 token 有效期等功能。
以上协议详细流程见本文 “3 OAuth 鉴权服务“。
### 5.2 研发云资源授权的粒度
1)代码中心:按照代码仓库的权限,不再细分到分支一级
2)制品中心:按照用户权限,不再细分
19