DApp 身份钱包静默登录
用身份钱包完成登录,为 DApp 返回可验证的身份签名。
接口 gpc_login 使用当前本地身份钱包,无需连接弹窗、签名弹窗或支付密码。Android/iOS 2.0.199(425)需安装本次 OTA 并重启。桌面支持需包含该接口的新客户端;普通浏览器和旧客户端不保证提供此方法。
接入示例
nonce 仅接受 16~128 位字母数字,由 DApp 后端生成、保存并与当前登录会话绑定。调用前无需 eth_requestAccounts。
// nonce 由后端生成:随机、一次性,绑定当前登录会话。
const { nonce } = await fetch('/auth/challenge').then(r => r.json());
const proof = await window.ethereum.request({
method: 'gpc_login',
params: [{ nonce }],
});
// 也可使用:const proof = await window.gpc.login({ nonce });
await fetch('/auth/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(proof),
});旧客户端返回不支持方法时,可提示用户更新钱包;不要把返回的钱包地址直接视为登录成功。
返回凭证
| 字段 | 含义 |
|---|---|
address | 身份钱包地址,EIP-55 格式 |
chainId | 当前 BSC 网络编号 |
origin | 钱包桥接层确定的页面来源,包含协议和非默认端口 |
nonce | DApp 后端提供的一次性随机挑战 |
issuedAt | 签发时间,UTC ISO 8601 |
expirationTime | 过期时间,签发后固定 5 分钟 |
message | 钱包生成的完整登录消息 |
signature | EIP-191 消息签名 |
消息按以下固定模板生成,各行使用 \n,结尾没有换行:
{origin 的 host,含非默认端口} wants you to sign in with your Ethereum account:
{address}
Sign in to this DApp with your GPC identity wallet. This request grants no transaction or asset permissions.
URI: {origin}
Version: 1
Chain ID: {chainId}
Nonce: {nonce}
Issued At: {issuedAt}
Expiration Time: {expirationTime}服务端验证
- 核对预期的 origin、网络,以及当前登录会话保存的 nonce。来源必须与自己的站点完全一致。
- 校验签发时间和过期时间,凭证期限应为 5 分钟,拒绝已过期或异常未来时间。
- 按上方模板重建消息,确认与 message 完全一致。
- 使用
ethers.verifyMessage(message, signature)恢复签名地址,与 address 比较。 - 验证成功后原子消费 nonce,再签发业务登录会话,阻止凭证重放。
DApp 自行管理登录会话和退出。钱包不替 DApp 签发服务端令牌。不能仅凭地址建立登录,也不能只验签而忽略来源和 nonce。
权限与错误码
仅接受单个 { nonce } 参数。额外字段、任意消息、类型化数据和交易参数均拒绝。接口不会授予 eth_accounts 权限,也不会改变 window.ethereum.selectedAddress;身份地址可能与当前付款钱包不同。
资金连接、personal_sign、类型化签名和交易仍使用原有确认流程。DApp 应分别管理身份登录与付款钱包连接。
| 错误码 | 原因 |
|---|---|
-32602 | 参数无效或包含额外字段 |
4100 | 没有身份钱包、密钥不可用,或签名期间身份切换 |
4200 | 外部钱包身份无法保证静默签名,或旧版不支持该接口 |