JavaScriptの
"クライアントを使用";
import type { Account } from "@ant-design/web3";
import { ConnectButton, Connector } from "@ant-design/web3";
import { Flex, Space } from "antd";
import React from "react";
import { JwtProvider } from "./JwtProvider";
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
SIWE実装ガイド:Dapp認証の強化
SIWE:イーサリアム身分証明を活用してDappの機能を強化する方法
SIWE(イーサリアムでサインイン)は、イーサリアム上でユーザーの身分を検証する方法であり、ウォレット取引を開始するのに似ており、ユーザーがウォレットをコントロールしていることを証明するために使用されます。現在の認証プロセスは非常に簡単で、ウォレットプラグイン内で情報に署名するだけで済み、大多数の一般的なウォレットプラグインがすでにサポートされています。
本文は主にイーサリアム上の署名シーンについて論じており、SolanaやSUIなどの他のパブリックチェーンには触れていません。
SIWEを使用する必要があるのはいつか
もしあなたのDappに以下の要件がある場合、SIWEの使用を検討できます:
しかし、あなたのDappが主に照会機能を持つ場合、例えばetherscanのようなアプリケーションの場合、必ずしもSIWEが必要というわけではありません。
あなたは「Dappでウォレット接続を行ったら、ウォレットの所有権が証明されたのではないか?」と尋ねるかもしれません。この言い方は部分的に正しいです。フロントエンドにとって、ウォレット接続は確かに身分を示しますが、バックエンドのサポートが必要なAPI呼び出しにおいては、アドレスを渡すだけでは不十分です。なぜなら、アドレスは公開情報であり、誰でも「借用」することができるからです。
SIWEの原理とプロセス
SIWEのプロセスは3つのステップに要約できます: ウォレットを接続する - 署名する - 身分証明を取得する。これらの3つのステップについて詳しく見ていきましょう。
ウォレットに接続する
これは一般的なWeb3操作であり、Dapp内でウォレットプラグインを通じてウォレットを接続します。
サイン
SIWEの署名手順にはNonce値の取得、ウォレット署名、バックエンド署名検証が含まれます。
まず、バックエンドインターフェースを呼び出してNonce値を取得する必要があります。バックエンドがリクエストを受け取った後、ランダムなNonce値を生成し、現在のアドレスに関連付けて、後続の署名の準備をします。
フロントエンドでNonce値を取得した後、Nonce値、ドメイン名、チェーンID、署名内容などを含む署名内容を構築します。通常、ウォレットが提供する署名方法を使用して署名を行います。
署名を構築した後、バックエンドに送信します。
ID を取得する
バックエンドで署名が検証されると、対応するユーザーの身分証明が返されます。例えばJWTのようなものです。フロントエンドはその後、バックエンドにリクエストを送信する際に対応するアドレスと身分証明を持参すれば、ウォレットの所有権を証明することができます。
! SIWEマニュアル:Dappをより強力にする方法は?
SIWEの実践
現在、多くのコンポーネントとライブラリがウォレット接続とSIWEへの迅速な接続をサポートしています。実際に操作してみましょう。目標は、あなたのDappがユーザー認証のためにJWTを返せるようにすることです。
注意、この例はSIWEの基本的なプロセスを紹介するためのものであり、運用環境での使用には安全上の問題がある可能性があります。
###の準備
私たちはNext.jsを使用してアプリケーションを開発しており、Node.js環境を準備する必要があります。Next.jsを使用する利点は、フロントエンドとバックエンドを分離することなく、フルスタックプロジェクトを直接開発できることです。
依存関係をインストールする
まずNext.jsをインストールし、プロジェクトディレクトリで次のコマンドを実行します:
npx create-next-app@14
指示に従ってインストールを完了した後、プロジェクトディレクトリに入り、起動します:
npm run dev
次にlocalhost:3000にアクセスすると、基本的なNext.jsプロジェクトが動いているのが見えます。
SIWEに関連する依存関係をインストールする
私たちはAnt Design Web3を使用してSIWEを実現しています。これは無料で、積極的にメンテナンスされており、使用体験は一般的なコンポーネントライブラリに似ていて、SIWEをサポートしています。
ターミナルに入力:
npm install antd @ant-design/web3 @ant-design/web3-wagmi wagmi viem @tanstack/react-query --save
ワグミのご紹介
Ant Design Web3のSIWEはWagmiライブラリに依存しています。私たちはlayout.tsxで関連するProviderをインポートし、プロジェクト全体でWagmiが提供するHooksを使用できるようにします。
まず、WagmiProvider 構成を定義します。
JavaScriptの "クライアントを使用"; import { getNonce, verifyMessage } from "@/app/api"; インポート{ メインネット、 メタマスク, Okxウォレット、 トークンポケット, WagmiWeb3ConfigProvider、 ウォレットコネクト、 } から "@ant-design/web3-wagmi"; import { QueryClient } from "@tanstack/react-query"; import React from "react"; import { createSiweMessage } from "viem/siwe"; import { http } from "wagmi"; import { JwtProvider } from "./JwtProvider";
const YOUR_WALLET_CONNECT_PROJECT_ID = "c07c0051c2055890eade3556618e38a6"; const queryClient = 新しいQueryClient();
const WagmiProvider: React.FC = ({ children }) => { const [jwt, setJwt] = React.useState(null);
リターン( <wagmiweb3configprovider siwe="{{" getnonce:="" async="" (address)=""> (await getNonce(address)).data, createMessage: (props) => { 戻り値 createSiweMessage({ ... props, statement: "Ant Design Web3" }); }, verifyMessage:非同期(message、signature) = > { const jwt = (await verifyMessage(message、signature)).data; setJwt(jwt); 帰る!! JWTの; }, }} chains={[Mainnet]} transports={{ [Mainnet.id]:http()、 }} walletConnect={{ projectId: YOUR_WALLET_CONNECT_PROJECT_ID、 }} wallets={[ MetaMask()、 WalletConnect()、 TokenPocket({ グループ: "人気", }), OkxWallet()、 ]} queryClient={クエリクライアント} > {子供} ); };
export default WagmiProvider;
私たちはAnt Design Web3が提供するProviderを使用し、SIWEのいくつかのインターフェースを定義しました。具体的な実装については後で紹介します。
そして、フロントエンドの接続入口として、ウォレット接続ボタンを追加します。
これで、私たちはSIWEを簡単に接続しました。
次に、接続ボタンを定義し、ウォレットを接続して署名を実現します:
JavaScriptの "クライアントを使用"; import type { Account } from "@ant-design/web3"; import { ConnectButton, Connector } from "@ant-design/web3"; import { Flex, Space } from "antd"; import React from "react"; import { JwtProvider } from "./JwtProvider";
export default 関数 App() { const jwt = React.useContext(JwtProvider);
const renderSignBtnText = ( defaultDom: React.ReactNode, アカウント?: アカウント ) => { const { アドレス } = アカウント ?? {}; const ellipsisAddress = アドレス ? ${address.slice(0, 6)}...${address.slice(-6)} : ""; ${ellipsisAddress}としてサインインします; };
リターン( <> {(アカウント) => ( <connectbutton.signin accountcomponent="{false}" renderbuttontext="{(dom)" ==""> renderSignBtnText(dom, account)} /> )} </connectbutton.signinです> {JWTの} ); }
こうして、私たちは最もシンプルなSIWEログインフレームワークを実現しました。
! SIWEマニュアル:Dappをより強力にする方法は?
インターフェースの実装
SIWEは、バックエンドがユーザーの身分証明を確認するのを助けるためにいくつかのインターフェースを必要とします。では、簡単に実装してみましょう。
ノンス
ノンスは、ウォレットが毎回署名する際に異なる署名内容を生成するために使用され、信頼性を向上させます。ノンスの生成は、ユーザーが提供するアドレスと関連付ける必要があり、検証の正確性を高めます。
Nonceの実装は非常に簡単です。まず、ランダムな文字列(を生成します。これはアルファベットと数字で構成されています)。それから、nonceとaddressの関連付けを行います。
JavaScriptの import { randomBytes } from "crypto"; import { addressMap } from ".. /cache";
非同期関数のエクスポート GET(request: Request) { const { searchParams } = 新しいURL(request.url); constアドレス= searchParams.get("アドレス");
if (!address) { 新しいError("無効なアドレス")をスローします。 } const nonce = randomBytes(16).toString("hex"); addressMap.set(住所、nonce); 戻り値 Response.json({ データ: ノンス, }); }
サインメッセージ
signMessageは内容に署名するために使用され、通常はウォレットプラグインを通じて行われます。私たちは一般的にメソッドを指定するだけで済みます。この例ではWagmiの署名メソッドを使用しています。
メッセージを確認する
ユーザーが署名した後、署名前の内容と署名を一緒にバックエンドに送信する必要があります。バックエンドは署名から内容を解析して比較し、一致すれば検証が通過したことを示します。
さらに、署名内容の安全性検証が必要であり、Nonce値がユーザーに割り当てられたものと一致するかどうかを確認します。検証が通過した後、後続の権限検証のためにユーザーにJWTを返します。
JavaScriptの import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; jwtを"jsonwebtoken"からインポートする; import { parseSiweMessage } from "viem/siwe"; import { addressMap } from ".. /cache";
const JWT_SECRET = "あなたの秘密鍵"; より安全なキーを使用し、適切な有効期限チェックなどを追加します
const publicClient = createPublicClient({ チェーン: メインネット, トランスポート:http()、 });
export async 関数 POST(request: Request) { const {署名、メッセージ} = await request.json();
const { nonce, アドレス = "0x" } = parseSiweMessage(message); console.log("nonce", nonce, address, addressMap);
// nonce値が一致するか検証する if (!nonce || nonce !== addressMap.get(アドレス)) { 新しいError("無効なナンス")をスローします。 }
// サイン内容の検証 const valid = await publicClient.verifySiweMessage({ メッセージ、 アドレス、 署名 });
if (!valid) { 新しいError("無効な署名")をスローします。 }
// jwtを生成して返す const token = jwt.sign({ アドレス }, JWT_SECRET, { expiresIn: "1h" }); 戻り値 Response.json({ データ: トークン, }); }
これで、基本的なSIWEログインを実装したDappが開発されました。
! SIWEマニュアル:Dappをより強力にする方法は?
最適化の提案
SIWEログインを行う際、デフォルトのRPCノードを使用すると、検証プロセスに約30秒かかる場合があります。したがって、インターフェースの応答時間を向上させるために、専用ノードサービスの使用を強くお勧めします。
EthereumのメインネットのHTTPS RPC接続を取得した後、コード内でpublicClientのデフォルトRPCを置き換えます:
JavaScriptの const publicClient = createPublicClient({ チェーン: メインネット, transport: http('), //ノードサービスRPCを取得 });
置き換え後、検証時間が大幅に短縮され、インターフェースの速度が明らかに向上します。
! SIWEマニュアル:Dappをより強力にする方法は?