登录与用户信息获取流程
本页给出从登录到取得敏感信息的完整链路,以及可直接复制到游戏脚本中的编排代码。各接口的参数与返回值定义见 API 总览。
角色
| 角色 | 职责 |
|---|---|
| Game | 游戏客户端脚本,调用 sud.* 接口 |
| SUD OP | OpenPaaS 运行环境,完成用户身份验证、敏感信息加密与签名 |
| Game SVR | 游戏服务端,消费 code 换取会话信息、签发自有登录态、验签并解密敏感数据 |
| SUD OP SVR | OpenPaaS 服务端,管理用户身份与会话密钥 |
完整链路
关键约束
code只能使用一次,由 Game SVR 消费;客户端不复用、不长期持有。auth.code2session必须在服务端调用,请求携带game_id与secret,严禁出现在客户端。session_key只保存在 Game SVR,不下发客户端、不写入前端可读取的配置、不输出到日志。Phase 3 的验签与解密必须使用 Phase 1 同一次登录取得的session_key。- 敏感数据端到端加密,客户端只做透传,任何客户端解密尝试都会失败。
rawData必须原样传递,Game SVR 验签时不得解析后重新序列化。- 基础信息与敏感信息分离:只需要昵称头像时用 sud.getUserInfo,链路更短且无需服务端参与加解密。
编排代码
三个接口都是回调式,下面先封装为 Promise 再按顺序编排。requestGameServerLogin 与 requestGameServerDecrypt 是游戏自己的服务端接口,需按各自后端实现替换,不是 OpenPaaS 提供的接口。
javascript
function login() {
return new Promise((resolve, reject) => {
sud.login({
success: (res) => resolve(res.code),
fail: (err) => reject(err),
complete: () => {},
});
});
}
function getUserInfo() {
return new Promise((resolve, reject) => {
sud.getUserInfo({
success: (res) => resolve(res),
fail: (err) => reject(err),
complete: () => {},
});
});
}
function getUserProfile() {
return new Promise((resolve, reject) => {
sud.getUserProfile({
success: (res) => resolve(res),
fail: (err) => reject(err),
complete: () => {},
});
});
}
async function startLoginFlow() {
// Phase 1:取得一次性 code,交给 Game SVR 换取登录态
const code = await login();
const session = await requestGameServerLogin(code);
// session = { token, openid },token 由 Game SVR 自行签发
// Phase 2:基础信息,可直接用于 UI 展示
const userInfo = await getUserInfo();
// Phase 3:敏感信息,客户端只透传,由 Game SVR 验签并解密
const profile = await getUserProfile();
const sensitive = await requestGameServerDecrypt(session.token, {
rawData: profile.rawData,
encryptedData: profile.encryptedData,
iv: profile.iv,
signature: profile.signature,
userInfo,
});
return { session, userInfo, sensitive };
}每一步都可能失败,应逐步处理错误,任一步失败都不要继续后续步骤;不要在最后统一捕获后就当作登录成功。
