164 lines
6.9 KiB
Plaintext
164 lines
6.9 KiB
Plaintext
|
|
2 签署 JWT
|
|||
|
|
扣子的 JWT 生成方式及部分参数定义沿用业界统一流程规范,但 JWT 中 Header 和 Payload 部分由扣子平台自行定义。
|
|||
|
|
在 JWT(JSON Web Tokens)的流程中,通常使用私钥来签署(sign)token。JWT 包含三部分,即 Header、Payload 和 signature,其中 header 和 payload 由参数拼接而成,signature 根据指定的签名算法和私钥对 Header 和 Payload 自动计算生成。三部分之间用点(.)分隔。详细的签署方式可参考JWT 官方文档。
|
|||
|
|
Header 和 Payload
|
|||
|
|
扣子平台对 Header 和 Payload 的定义如下:
|
|||
|
|
Header
|
|||
|
|
Header 部分的参数定义如下:
|
|||
|
|
参数
|
|||
|
|
类型
|
|||
|
|
是否必选
|
|||
|
|
说明
|
|||
|
|
alg
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
签名使用的加密算法。固定为 RS256,即非对称加密算法,一种基于 RSA(非对称加密算法)+ SHA256(安全哈希函数)的签名算法,该算法使用私钥进行签名,公钥进行验证。
|
|||
|
|
typ
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
固定为 JWT。
|
|||
|
|
kid
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
OAuth 应用的公钥指纹,可以在OAuth 应用页面找到这个应用,在操作列单击编辑图标,进入配置页面查看公钥指纹。
|
|||
|
|
|
|||
|
|
|
|||
|
|
Header 示例如下:
|
|||
|
|
{
|
|||
|
|
"alg": "RS256", // 固定为RS256
|
|||
|
|
"typ": "JWT", // 固定为 JWT
|
|||
|
|
"kid": "gdehvaDegW....." // OAuth 应用的公钥指纹
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Payload:
|
|||
|
|
Payload 部分的参数定义如下:
|
|||
|
|
参数
|
|||
|
|
类型
|
|||
|
|
是否必选
|
|||
|
|
说明
|
|||
|
|
iss
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
OAuth 应用的 ID,可以在OAuth 应用页面查看。
|
|||
|
|
aud
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
扣子 API 的 Endpoint,即 api.coze.cn。
|
|||
|
|
iat
|
|||
|
|
Integer
|
|||
|
|
必选
|
|||
|
|
JWT 开始生效的时间,Unixtime 时间戳格式,精确到秒。一般为当前时刻。
|
|||
|
|
exp
|
|||
|
|
Integer
|
|||
|
|
必选
|
|||
|
|
JWT 过期的时间,Unixtime 时间戳格式,精确到秒。必须晚于 iat。
|
|||
|
|
jti
|
|||
|
|
String
|
|||
|
|
必选
|
|||
|
|
随机字符串,用于防止重放攻击。建议长度大于 32 字节。每次签署 JWT 时应指定为不同的字符串。
|
|||
|
|
session_name
|
|||
|
|
String
|
|||
|
|
可选
|
|||
|
|
访问令牌的会话标识。目前仅限在会话隔离场景下使用,即将 session_name 指定为用户在业务侧的 UID,以此区分不同业务侧用户的对话历史。
|
|||
|
|
若未指定 session_name,不同用户的对话历史可能会掺杂在一起。
|
|||
|
|
会话隔离的详细实现方法请参见如何实现会话隔离。
|
|||
|
|
|
|||
|
|
session_context
|
|||
|
|
Object
|
|||
|
|
可选
|
|||
|
|
会话上下文信息,包含设备相关信息等。
|
|||
|
|
|
|||
|
|
session_context.device_info
|
|||
|
|
Object
|
|||
|
|
可选
|
|||
|
|
用于配置设备相关信息,扣子平台基于该部分信息对设备做用量管控以及账单记录。
|
|||
|
|
该参数为企业白版白名单功能,需要联系扣子商务经理开通后才能使用。硬件设备用量管控的具体操作可参考硬件设备用量查询和配额管控。
|
|||
|
|
session_context.device_info.device_id
|
|||
|
|
String
|
|||
|
|
可选
|
|||
|
|
IoT 等硬件设备 ID,一个设备对应一个唯一的设备号。
|
|||
|
|
当需要记录设备用量或对设备用量进行管控时,需要填写该参数,否则,无法对设备进行用量管控,用量统计页面对应的设备 ID 将显示为 N/A。
|
|||
|
|
session_context.device_info.custom_consumer
|
|||
|
|
|
|||
|
|
String
|
|||
|
|
可选
|
|||
|
|
自定义维度的实体 ID,你可以根据业务需要进行设置,例如 APP 上的用户名等。
|
|||
|
|
当需要记录设备用量或对设备用量进行管控,需要填写该参数,否则,无法对设备进行用量管控,用量统计页面对应的自定义 ID 将显示为 N/A。
|
|||
|
|
device_id 和 custom_consumer 建议选择其中一个即可。
|
|||
|
|
custom_consumer 参数用于设备用量管控,与对话等 API 传入的 user_id 无关,user_id 主要用于上下文、数据库隔离等场景。
|
|||
|
|
出于数据隐私及信息安全等方面的考虑,不建议使用业务系统中定义的用户敏感标识(如手机号等)作为 custom_consumer 的值。
|
|||
|
|
|
|||
|
|
|
|||
|
|
Payload 示例如下:
|
|||
|
|
{
|
|||
|
|
"iss": "310000000002", // OAuth 应用的 ID
|
|||
|
|
"aud": "api.coze.cn", // 扣子 API 的 Endpoint
|
|||
|
|
"iat": 1516239022, // JWT 开始生效的时间,秒级时间戳
|
|||
|
|
"exp": 1516259022, // JWT 过期时间,秒级时间戳
|
|||
|
|
"jti": "fhjashjgkhalskj", // 随机字符串,防止重放攻击
|
|||
|
|
"session_name": "user_2222", //用户在业务侧的 UID
|
|||
|
|
"session_context": {
|
|||
|
|
"device_info": {
|
|||
|
|
"device_id": "1234567890" // IoT 等硬件设备的唯一标识 ID
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
示例代码
|
|||
|
|
你可以直接参考以下示例代码签署 JWT。
|
|||
|
|
# You must run `pip install PyJWT cryptography` to install the PyJWT and the cryptography packages in order to use this script.
|
|||
|
|
|
|||
|
|
#!/usr/bin/env python3
|
|||
|
|
import sys
|
|||
|
|
import time
|
|||
|
|
import uuid
|
|||
|
|
|
|||
|
|
import jwt
|
|||
|
|
|
|||
|
|
# 替换为你的实际 Coze App 私钥
|
|||
|
|
signing_key = '''
|
|||
|
|
-----BEGIN PRIVATE KEY-----
|
|||
|
|
xxxxxxxxxxxxxxxxxx
|
|||
|
|
-----END PRIVATE KEY-----
|
|||
|
|
'''
|
|||
|
|
|
|||
|
|
payload = {
|
|||
|
|
'iat': int(time.time()),
|
|||
|
|
'exp': int(time.time()) + 600,
|
|||
|
|
"jti": str(uuid.uuid4()),
|
|||
|
|
'aud': 'api.coze.cn',
|
|||
|
|
'iss': '1127900106117' # 替换为你的实际 Coze App ID
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
headers = {
|
|||
|
|
'kid': '_v0VjcMlLdQc3tRTD3jC5Xz29TUnKQOhtuD5k-gpyf4' # 替换为你的实际 Coze App 公钥指纹
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Create JWT with headers
|
|||
|
|
encoded_jwt = jwt.encode(payload, signing_key, algorithm='RS256', headers=headers)
|
|||
|
|
|
|||
|
|
print(f"JWT: {encoded_jwt}")
|
|||
|
|
|
|||
|
|
最终生成的 JWT 示例如下:
|
|||
|
|
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InZZd2ZsdFR1OWZBbWtwWFhSdnR5UmREc3RONVMzZWNFcDFqVzB6dVQyRE****.eyJpc3MiOiIzMTAwMDAwMDAwMDIiLCJhdWQiOiJhcGkuY296ZS5jb20iLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTkxNjI1OTAyMiwianRpIjoiZmhqaGFsc2tqZmFkc2pld3F****.CuoiCCF-nHFyGmu2EKlwFoyd3uDyKQ3Drc1CrXQyMVySTzZlZd2M7zKWsziB3AktwbUZiRJlQ1HbghR05CW2YRHwKL4-dlJ4koR3onU7iQAO5DkPCaIxbAuTsQobtCAdkkZTg8gav9EnN1QN_1xq0w8BzuuhS7wCeY8UbaskkTK9GnO4eU9tEINmVw-2CrfB-kNbEHlEDwXfcrb4YPpkw3GhmuPShenNLObfSWS0CqIyakXL8qD5AgXLoB-SejAsRdzloSUInNXENJHfSVMkThxRhJy7yEjX3BmculC54fMKENRfLElBqwJyLLUjeRHsYnaru2ca4W8_yaPJ7F****
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
3 获取访问令牌
|
|||
|
|
应用程序调用 通过 JWT 获取 Oauth Access Token API ,请求 Header 中携带 JWT,扣子服务端会在响应中通过 access_token 字段返回访问令牌。
|
|||
|
|
请求示例如下:
|
|||
|
|
curl --location --request POST 'https://api.coze.cn/api/permission/oauth2/token' \
|
|||
|
|
--header 'Content-Type: application/json' \
|
|||
|
|
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InZZd2ZsdFR1OWZBbWtwWFhSdnR5UmREc3RONVMzZWNFcDFqVzB6dVQyRE****.eyJpc3MiOiIzMTAwMDAwMDAwMDIiLCJhdWQiOiJhcGkuY296ZS5jb20iLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTkxNjI1OTAyMiwianRpIjoiZmhqaGFsc2tqZmFkc2pld3F****.CuoiCCF-nHFyGmu2EKlwFoyd3uDyKQ3Drc1CrXQyMVySTzZlZd2M7zKWsziB3AktwbUZiRJlQ1HbghR05CW2YRHwKL4-dlJ4koR3onU7iQAO5DkPCaIxbAuTsQobtCAdkkZTg8gav9EnN1QN_1xq0w8BzuuhS7wCeY8UbaskkTK9GnO4eU9tEINmVw-2CrfB-kNbEHlEDwXfcrb4YPpkw3GhmuPShenNLObfSWS0CqIyakXL8qD5AgXLoB-SejAsRdzloSUInNXENJHfSVMkThxRhJy7yEjX3BmculC54fMKENRfLElBqwJyLLUjeRHsYnaru2ca4W8_yaPJ7F****' \
|
|||
|
|
--data '{
|
|||
|
|
"duration_seconds": 86399,
|
|||
|
|
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
|||
|
|
}'
|
|||
|
|
|
|||
|
|
返回示例如下:
|
|||
|
|
{
|
|||
|
|
"access_token": "czs_RQOhsc7vmUzK4bNgb7hn4wqOgRBYAO6xvpFHNbnl6RiQJX3cSXSguIhFDzgy****",
|
|||
|
|
"expires_in": 1721135859
|
|||
|
|
}
|