SIWE(Sign-In with Ethereum)登录流程概述

  • 曲弯
  • 发布于 15小时前
  • 阅读 35

SIWE(Sign-InwithEthereum)登录流程概述什么是SIWE?SIWE(Sign-InwithEthereum)是一个以太坊登录的开放标准(EIP-4361),它允许用户通过钱包签名一条结构化的消息来安全地验证身份,而无需进行链上交易或支付Gas费。核心思想SIWE

<!--StartFragment-->

SIWE(Sign-In with Ethereum)登录流程概述

什么是SIWE?

SIWE(Sign-In with Ethereum)是一个以太坊登录的开放标准(EIP-4361),它允许用户通过钱包签名一条结构化的消息来安全地验证身份,而无需进行链上交易或支付Gas费。

核心思想

SIWE的核心是"用户用私钥对一条结构化的登录消息签名,服务端通过验证签名来确认身份"。整个过程完全链下,无需链上交易。

整体流程(简化版)

graph TD
    A[用户访问网站] --> B[前端请求登录]
    B --> C[后端生成随机Nonce]
    C --> D[返回登录消息模板]
    D --> E[钱包弹出签名请求]
    E --> F[用户查看并签名]
    F --> G[发送签名到后端验证]
    G --> H[验证成功创建会话]
    H --> I[返回会话令牌]

详细步骤

第1步:前端请求登录挑战

前端向后端请求一个登录挑战,后端返回一个结构化的登录消息模板,包含:

  • 域名
  • 用户地址
  • 随机Nonce
  • 过期时间
  • 声明语句

示例登录消息:

example.com wants you to sign in with your Ethereum account:
0x1234...5678

Please sign to login to Example App.

URI: https://example.com
Version: 1
Chain ID: 1
Nonce: abc123def456
Issued At: 2023-10-01T10:00:00Z
Expiration Time: 2023-10-01T10:05:00Z

第2步:用户签名

前端将这条结构化的消息发送给用户的钱包(如MetaMask),钱包弹出签名请求,用户可以看到完整的消息内容并确认签名。

关键特点:

  • 用户可以看到完整的消息内容,知道自己在为什么签名
  • 这是链下签名,无需Gas费
  • 签名是一次性的,针对特定Nonce

第3步:后端验证签名

前端将签名结果原始消息用户地址一起发送给后端,后端进行验证:

  1. 检查消息完整性:验证消息中的域名、过期时间等是否正确
  2. 验证签名有效性:通过密码学验证签名确实是由该地址对应的私钥生成的
  3. 检查Nonce:确保这个Nonce是有效的、未使用过的
  4. 检查时间:确保消息没有过期

第4步:建立会话

验证成功后,后端:

  1. 标记这个Nonce为已使用(防止重放攻击)
  2. 创建一个会话(如JWT令牌)
  3. 将会话令牌返回给前端

第5步:后续请求

前端在后续请求中携带会话令牌,后端验证令牌有效性并返回相应的用户数据。

SIWE消息的完整结构

一个标准的SIWE消息包含以下字段:

{域名} wants you to sign in with your Ethereum account:
{用户地址}

{声明语句}

URI: {请求URI}
Version: 1
Chain ID: {链ID}
Nonce: {随机Nonce}
Issued At: {签发时间}
Expiration Time: {过期时间}
Not Before: {生效时间}  # 可选
Request ID: {请求ID}  # 可选
Resources:  # 可选
- {资源1}
- {资源2}

为什么SIWE更安全?

  1. 结构化消息:用户清楚地知道自己在为什么签名
  2. 防重放攻击:每个Nonce只能使用一次
  3. 上下文明确:包含域名、时间等信息,防止跨站攻击
  4. 标准化:EIP-4361是开放标准,各钱包统一支持
  5. 无Gas成本:纯链下操作,无需支付费用

与传统签名方案的对比

方面 传统方案 SIWE方案
用户可见性 随机字符串,用户不知道签的是什么 结构化的英文消息,用户完全清楚内容
标准化 无标准,每个应用自己定义 统一的EIP-4361标准
安全性 依赖应用实现,可能有安全漏洞 标准化验证,安全性更高
钱包支持 钱包只显示签名字符串 钱包可以专门优化SIWE显示
用户体验 较差,用户不明确签名的内容 较好,用户知道这是登录操作

实际应用示例

// 前端代码示例
async function signInWithEthereum() {
  // 1. 连接钱包获取地址
  const accounts = await window.ethereum.request({ 
    method: 'eth_requestAccounts' 
  });
  const address = accounts[0];

  // 2. 从后端获取登录消息
  const response = await fetch('/api/auth/nonce');
  const { message } = await response.json();

  // 3. 用户签名
  const signature = await window.ethereum.request({
    method: 'personal_sign',
    params: [message, address],
  });

  // 4. 发送验证
  const verifyResponse = await fetch('/api/auth/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ message, signature, address }),
  });

  // 5. 获取会话令牌
  const { token } = await verifyResponse.json();
  return token;
}

总结

SIWE的核心流程是:

  1. 后端生成:包含随机Nonce的结构化登录消息
  2. 用户签名:用户查看完整消息内容并确认签名
  3. 后端验证:验证签名、Nonce、过期时间等
  4. 建立会话:创建传统Web会话令牌

关键优势

  • ✅ 用户友好:知道自己在为什么签名
  • ✅ 标准化:统一的消息格式
  • ✅ 无Gas:链下签名,无需费用
  • ✅ 安全:防重放、防跨站
  • ✅ 钱包支持好:主流钱包都支持

SIWE是目前以太坊登录的事实标准,被OpenSea、Uniswap等主流dApp采用,提供了最佳的安全性和用户体验平衡。

<!--EndFragment-->

点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
曲弯
曲弯
0xb51E...CADb
Don't give up if you love it. If you don't, then that's not good either, because one shouldn't do things they don't enjoy.