cm Studio 通行证
为第三方平台提供统一身份认证接入能力,用户只需一个通行证账号即可登录所有接入平台。
SSO 单点登录 · 面向开发者概述
cm Studio 通行证(cmpass)是 cm Studio 统一身份认证平台,为旗下及合作平台提供 SSO 单点登录服务。
作为第三方平台开发者,接入后你的用户可以:
- 使用 cm Studio 通行证账号一键登录你的平台
- 无需在你的平台单独注册,降低用户门槛
- 通过加密令牌安全传递身份,无需明文传递密码
client_id 白名单),目前不支持自助注册。
接入地址
| 环境 | 地址 |
|---|---|
| 生产 | https://pass.kscm.top |
| SSO 入口 | https://pass.kscm.top/ssologin.php?client_id={你的平台ID} |
工作原理
cmpass SSO 采用「一次性令牌」机制,整体流程如下:
-
平台发起跳转
用户点击"使用 cm Studio 通行证登录",平台将用户重定向到 cmpass SSO 入口,携带
client_id参数。 - 用户登录 / 确认授权 用户在 cmpass 页面完成登录(或使用已有登录态),点击"授权并跳转"。
-
生成一次性令牌
cmpass 为本次登录生成一个随机的 32 位一次性令牌(
temp_key),并将用户的身份哈希值存入服务端 KV 存储。 -
跳转回平台
cmpass 将用户重定向到你平台预先注册的
sso_endpoint,URL 中携带?key=temp_key。 -
平台验证令牌
你的平台从 URL 取出
key,将其作为key_id调用 cmpass 令牌查询接口,换取用户的唯一身份标识(SHA256 哈希),完成登录。
key 只能被成功查询一次,查询成功后即失效。请在收到跳转后立即查询,勿缓存或复用。
第一步 · 申请接入
向 cm Studio 管理员提交以下信息,申请将你的平台加入注册表:
| 字段 | 说明 | 示例 |
|---|---|---|
client_id | 平台唯一标识符(英文小写,简短易记) | mygame |
| 平台名称 | 在 SSO 授权页面显示给用户 | 我的游戏平台 |
| 平台首页 URL | 用于"返回平台"链接 | https://mygame.example.com/ |
| 平台图标 URL | 显示在授权页面,建议 64×64 PNG | https://mygame.example.com/favicon.png |
| SSO 接收端点 | 令牌回调地址,必须可公网访问 | https://mygame.example.com/cmpasssso.php |
| 平台简介 | 显示在授权页面的一句话说明 | 独立游戏创作与发布平台 |
| 主题色(可选) | 授权页面的高亮色 | #e55a2b |
client_id 确认。注册表更新后即可使用,无需额外密钥。
第二步 · 实现 SSO 接收端点
你需要在自己的平台部署一个接收页面(推荐路径 /cmpasssso.php),用于接收 cmpass 的跳转回调。
端点职责
- 从 URL 获取
key参数 - 调用 cmpass 令牌查询 API,获取用户身份哈希
- 在你的数据库中查找或创建对应用户
- 写入登录态,跳转到平台首页
完整示例代码(PHP)
PHP<?php
/**
* cmpasssso.php — cm Studio 通行证 SSO 回调端点
* 部署于你的平台,接收 cmpass 的跳转
*/
// 1. 从回调 URL 中获取令牌(URL 参数名为 key)
$key = isset($_GET['key']) ? trim($_GET['key']) : '';
if (empty($key)) {
header('Location: /login?error=missing_key');
exit;
}
// 2. 向 cmpass 查询令牌(API 参数名为 key_id)
$identity = cmpass_verify_token($key);
if ($identity === null) {
header('Location: /login?error=invalid_token');
exit;
}
// $identity 是一个 64 位十六进制字符串(SHA256 哈希)
// 这是该用户在 cmpass 的唯一身份标识,永不变化
// 3. 在你的数据库中查找用户
$user = db_find_user_by_cmpass_id($identity);
if (!$user) {
// 新用户,可以自动创建账号
$user = db_create_user_from_cmpass([
'cmpass_id' => $identity,
'username' => 'cmpass_' . substr($identity, 0, 8),
]);
}
// 4. 写入登录态,完成登录
$_SESSION['user_id'] = $user['id'];
header('Location: /dashboard');
exit;
// ─── 辅助函数 ───────────────────────────────
function cmpass_verify_token(string $key_id): ?string {
$url = 'https://pass.kscm.top/key.php?key_id=' . urlencode($key_id);
$resp = @file_get_contents($url);
if ($resp === false) return null;
$data = json_decode($resp, true);
if (!$data || $data['error'] === true) return null;
return $data['key']; // 64 位 SHA256 字符串
}
第三步 · 在你的平台发起 SSO 跳转
在你平台的登录页面,添加"使用 cm Studio 通行证登录"按钮,点击后跳转到以下地址:
URLhttps://pass.kscm.top/ssologin.php?client_id={你的client_id}
HTML 示例
HTML<a href="https://pass.kscm.top/ssologin.php?client_id=mygame"
class="btn-cmpass">
使用 cm Studio 通行证登录
</a>
PHP 跳转示例
PHP// 重定向到 cmpass SSO(例如:用户点击登录按钮后)
$client_id = 'mygame';
$sso_url = 'https://pass.kscm.top/ssologin.php?client_id=' . urlencode($client_id);
header('Location: ' . $sso_url);
exit;
sso_endpoint。
第四步 · 在回调端点完成身份验证
cmpass 跳转到你的 sso_endpoint 时,URL 中会携带 key 参数:
URLhttps://mygame.example.com/cmpasssso.php?key=a3f8c2d19e7b4056...
你需要用这个 key 调用令牌查询 API 来验证用户身份(详见下一节)。
令牌查询 API
收到回调 key 参数后,在服务端调用此接口换取用户身份标识。注意:回调 URL 中的参数名为 key,但调用此 API 时需将其作为 key_id 传递。
请求
| 属性 | 值 |
|---|---|
| 方法 | GET |
| 地址 | https://pass.kscm.top/key.php |
Query 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key_id |
string | 必填 | 从回调 URL 中获取的一次性令牌(32 位十六进制,即回调 URL 中的 key 值) |
响应
所有响应均为 JSON 格式,固定包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
code | int | HTTP 状态码:200 成功 / 400 参数缺失 / 404 令牌不存在 |
error | bool | 是否发生错误 |
msg | string | 结果描述 |
key | string|null | 成功时为 64 位 SHA256 身份标识;失败时为 null |
成功(200)
JSON{
"code": 200,
"error": false,
"msg": "success",
"key": "e3b0c44298fc1c149afbf89c...(64位SHA256字符串)"
}
失败 — 缺少参数(400)
JSON{
"code": 400,
"error": true,
"msg": "缺少 key_id 参数",
"key": null
}
失败 — 令牌无效或已使用(404)
JSON{
"code": 404,
"error": true,
"msg": "key_id 不存在或已失效",
"key": null
}
key_id 无法被第二次查询。请在收到回调后立即消费,勿缓存。
调用示例
PHPfunction cmpass_verify_token(string $key_id): ?string {
$url = 'https://pass.kscm.top/key.php?key_id=' . urlencode($key_id);
$resp = @file_get_contents($url);
if ($resp === false) return null;
$data = json_decode($resp, true);
if (!$data || $data['error'] === true) return null;
return $data['key']; // 64 位 SHA256 身份标识
}
Pythonimport requests
def cmpass_verify_token(key_id: str) -> str | None:
resp = requests.get(
'https://pass.kscm.top/key.php',
params={'key_id': key_id},
timeout=10
)
data = resp.json()
if data.get('error') is False:
return data['key']
return None
Node.jsasync function cmpassVerifyToken(keyId) {
const res = await fetch(
`https://pass.kscm.top/key.php?key_id=${encodeURIComponent(keyId)}`
);
const data = await res.json();
return data.error === false ? data.key : null;
}
用户身份标识
验证成功后,响应中的 key 字段是一个 64 位十六进制字符串,这是该 cmpass 用户在你平台的唯一身份标识。
特性
| 特性 | 说明 |
|---|---|
| 唯一性 | 每个 cmpass 账号对应唯一的身份标识,不会重复 |
| 不可逆 | 是用户内部通行密钥的 SHA256 哈希,无法反推出用户名或密码 |
| 稳定性 | 同一用户每次登录得到相同的值,可安全用于绑定你平台的账号 |
| 格式 | 64 位十六进制字符串,小写 |
推荐存储方式
在你的用户表中添加 cmpass_id 字段(VARCHAR 64,唯一索引),用于关联 cmpass 账号与你平台的本地账号:
SQLALTER TABLE users
ADD COLUMN cmpass_id VARCHAR(64) NULL UNIQUE,
ADD INDEX idx_cmpass_id (cmpass_id);
错误处理
常见场景处理建议
| 场景 | 原因 | 处理方式 |
|---|---|---|
API 返回 code: 404 |
令牌已被使用、过期,或 URL 中的 key 被截断 | 引导用户重新从你的登录页发起 SSO |
API 返回 code: 400 |
未传入 key_id 参数(通常是代码 bug) |
检查回调端点是否正确从 URL 取出了 key 值 |
| 令牌查询超时或网络错误 | cmpass 服务或网络短暂不可用 | 显示友好错误,提示稍后重试;不要让用户停在空白页 |
收到 key 但为空字符串 |
异常跳转或参数丢失 | 直接跳转回登录页,不要调用 API |
| 同一身份标识重复登录 | 正常情况(用户多次登录) | 直接复用已绑定的本地账号,更新登录态即可 |
错误页面示例
PHP// cmpasssso.php 中的错误处理模板
$key = isset($_GET['key']) ? trim($_GET['key']) : '';
if (empty($key)) {
show_error('登录参数缺失,请重新从登录页发起。');
exit;
}
$identity = cmpass_verify_token($key);
if ($identity === null) {
show_error('登录凭证已失效,请重新登录。');
exit;
}
// ...继续正常登录流程
function show_error(string $msg): void {
// 渲染一个友好的错误页,并提供"返回登录"的链接
header('HTTP/1.1 401 Unauthorized');
echo "<p>{$msg}</p><a href='/login'>重新登录</a>";
}
安全建议
- 服务端验证:令牌查询必须在服务端发起,禁止在前端 JS 中请求令牌接口。
- HTTPS:你的
sso_endpoint和平台域名应使用 HTTPS,防止key参数在传输中被截获。 - 立即消费令牌:收到回调后应立即调用 API 消费令牌,不要延迟。令牌一经查询即失效,无法重放。
- 不要信任 URL 中的用户名:cmpass 回调只携带
key,用户身份来自服务端验证结果,不要信任任何平台自己拼接的用户参数。 - 防止 CSRF:建议在发起 SSO 前在 Session 中生成随机 nonce,并在回调时验证来源页面合法性(当前版本 cmpass 不传递 state,需自行实现)。
常见问题
用户在 cmpass 修改了密码,我平台的登录会受影响吗?
不会。用户身份标识(SHA256 哈希)由其内部通行密钥派生,通行密钥在账号创建时生成且不会改变。修改密码不影响身份标识。
我可以获取用户的用户名或邮箱吗?
当前版本只提供匿名身份标识,不暴露用户名或邮箱等个人信息。如有需求,可在授权完成后引导用户在你平台主动填写个人资料。
令牌有有效期吗?
令牌没有明确的时间过期机制,但每个令牌只能被成功查询一次。用户完成一次 SSO 登录后,该令牌即永久失效。如果用户需要再次登录,需重新发起 SSO 流程,生成新令牌。
用户取消授权了怎么办?
若用户在 cmpass 授权页点击"返回"而非"授权并跳转",你的 sso_endpoint 不会收到任何回调。你的登录页应有超时或用户主动取消的处理逻辑。
同一用户能绑定多个平台账号吗?
可以。每个接入平台独立维护自己的用户数据,同一个 cmpass 身份标识可以分别绑定到不同平台的不同账号。
接入后需要维护什么?
通常无需维护。只要你的 sso_endpoint 正常响应,SSO 即可持续工作。如果你的域名或端点地址发生变更,需联系 cm Studio 更新注册表。
有其他问题或需要申请接入?请通过 3281479085@qq.com 联系开发者。