SIWE : Comment réaliser l'identification Ethereum pour améliorer les fonctionnalités des Dapps
SIWE(Se connecter avec Ethereum) est une méthode de vérification de l'identification des utilisateurs sur la blockchain Ethereum, similaire à l'initiation d'une transaction par portefeuille, utilisée pour prouver le contrôle de l'utilisateur sur le portefeuille. Le processus d'identification actuel est déjà très simple, il suffit de signer les informations dans le plugin de portefeuille, la plupart des plugins de portefeuille courants sont déjà supportés.
Cet article discute principalement des scénarios de signature sur Ethereum, sans aborder d'autres chaînes publiques comme Solana ou SUI.
Quand devez-vous utiliser SIWE
Si votre Dapp a les besoins suivants, vous pouvez envisager d'utiliser SIWE :
Avoir son propre système d'identification
Besoin de consulter des informations liées à la vie privée des utilisateurs
Mais si votre Dapp est principalement une application de requête, comme une application similaire à Ethereum, alors il n'est pas nécessaire d'utiliser SIWE.
Vous pourriez demander, après avoir connecté le portefeuille sur Dapp, n'est-ce pas une preuve de propriété du portefeuille ? Cette affirmation est en partie correcte. Pour le front-end, la connexion du portefeuille indique effectivement l'identification, mais pour les appels API nécessitant un support back-end, il ne suffit pas de transmettre l'adresse, car l'adresse est une information publique, et n'importe qui peut "emprunter".
Principe et processus de SIWE
Le processus de SIWE peut être résumé en trois étapes : connexion au portefeuille - signature - obtention de l'identification. Examinons ces trois étapes en détail.
connecter le portefeuille
C'est une opération Web3 courante qui connecte votre portefeuille dans la Dapp via un plugin de portefeuille.
signature
Les étapes de signature de SIWE comprennent l'obtention de la valeur Nonce, la signature du portefeuille et la vérification de la signature par le backend.
Tout d'abord, il est nécessaire d'appeler l'interface backend pour obtenir la valeur Nonce. Après avoir reçu la demande, le backend générera une valeur Nonce aléatoire et l'associera à l'adresse actuelle, préparant ainsi la signature ultérieure.
Après avoir obtenu la valeur Nonce par le front-end, construisez le contenu de la signature, y compris la valeur Nonce, le nom de domaine, l'ID de la chaîne, le contenu de la signature, etc. En général, une méthode de signature fournie par le portefeuille est utilisée pour signer.
Après avoir construit la signature, envoyez-la au backend.
obtenir l'identification
Après validation de la signature par l'arrière-plan, un identifiant utilisateur correspondant sera renvoyé, tel que JWT. Lors de l'envoi de la demande au backend par le frontend, il suffit d'inclure l'adresse correspondante et l'identification pour prouver la propriété du portefeuille.
Pratique SIWE
Il existe maintenant de nombreux composants et bibliothèques qui prennent en charge la connexion rapide aux portefeuilles et au SIWE. Faisons une opération pratique, l'objectif est de permettre à votre Dapp de renvoyer un JWT pour l'authentification des utilisateurs.
Attention, cet exemple est uniquement utilisé pour présenter le processus de base de SIWE, son utilisation dans un environnement de production peut présenter des problèmes de sécurité.
travaux préparatoires
Nous utilisons Next.js pour développer des applications, et il est nécessaire de préparer l'environnement Node.js. L'avantage d'utiliser Next.js est qu'il permet de développer directement des projets full stack, sans avoir besoin de séparer le front-end et le back-end.
installer les dépendances
Tout d'abord, installez Next.js, exécutez dans le répertoire du projet :
npx create-next-app@14
Après avoir terminé l'installation selon les instructions, accédez au répertoire du projet et démarrez :
npm run dev
Ensuite, accédez à localhost:3000 pour voir le projet Next.js de base en cours d'exécution.
Installer les dépendances liées à SIWE
Nous utilisons Ant Design Web3 pour implémenter SIWE, car il est gratuit, activement maintenu, offre une expérience utilisateur similaire à celle des bibliothèques de composants ordinaires et prend en charge SIWE.
La bibliothèque SIWE d'Ant Design Web3 dépend de Wagmi. Nous avons importé le Provider correspondant dans layout.tsx pour que l'ensemble du projet puisse utiliser les Hooks fournis par Wagmi.
D'abord, définissez la configuration de WagmiProvider :
javascript
"use client";
import { getNonce, verifyMessage } from "@/app/api";
import {
Mainnet,
MetaMask,
OkxWallet,
TokenPocket,
WagmiWeb3ConfigProvider,
WalletConnect,
} de "@ant-design/web3-wagmi";
import { QueryClient } from "@tanstack/react-query";
importer React de "react";
import { createSiweMessage } from "viem/siwe";
importer { http } de "wagmi";
import { JwtProvider } from "./JwtProvider";
const YOUR_WALLET_CONNECT_PROJECT_ID = "c07c0051c2055890eade3556618e38a6";
const queryClient = new QueryClient();
Nous utilisons le Provider fourni par Ant Design Web3 et avons défini certaines interfaces SIWE, dont la mise en œuvre sera présentée ultérieurement.
Ensuite, ajoutez un bouton de connexion au portefeuille, en tant qu'entrée de connexion frontale.
À ce stade, nous avons déjà intégré simplement SIWE.
Ensuite, définissez un bouton de connexion pour établir la connexion au portefeuille et signer :
javascript
"use client";
importer type { Compte } from "@ant-design/web3";
import { ConnectButton, Connector } from "@ant-design/web3";
import { Flex, Space } from "antd";
importer React de "react";
import { JwtProvider } from "./JwtProvider";
export default function App() {
const jwt = React.useContext(JwtProvider);
const renderSignBtnText = (
defaultDom: React.ReactNode,
compte?: Compte
) => {
const { address } = account ?? {};
const ellipsisAddress = address
? ${address.slice(0, 6)}...${address.slice(-6)}
: "";
retournez Connexion en tant que ${ellipsisAddress};
};
Ainsi, nous avons réalisé un cadre de connexion SIWE des plus simples.
Implémentation de l'interface
SIWE nécessite certaines interfaces pour aider l'arrière-plan à vérifier l'identification des utilisateurs. Maintenant, réalisons cela simplement.
Nonce
Le nonce est utilisé pour générer un contenu de signature différent à chaque fois que le portefeuille signe, améliorant ainsi la fiabilité. La génération du nonce doit être associée à l'adresse fournie par l'utilisateur afin d'améliorer la précision de la vérification.
L'implémentation du nonce est très directe, tout d'abord, générez une chaîne aléatoire ( composée de lettres et de chiffres ), puis établissez une association entre le nonce et l'adresse :
javascript
import { randomBytes } from "crypto";
import { addressMap } from "../cache";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const address = searchParams.get("address");
signMessage est utilisé pour signer du contenu, généralement effectué via un plugin de portefeuille, nous avons généralement juste besoin de spécifier la méthode. Dans cet exemple, nous utilisons la méthode de signature de Wagmi.
vérifierMessage
Après que l'utilisateur ait signé, il doit envoyer le contenu avant la signature avec la signature au backend pour vérification. Le backend extrait le contenu de la signature pour comparaison; s'ils correspondent, cela signifie que la vérification est réussie.
De plus, il est nécessaire de vérifier la sécurité du contenu de la signature, par exemple en vérifiant si la valeur Nonce est cohérente avec celle attribuée à l'utilisateur. Une fois la vérification réussie, renvoyez le JWT à l'utilisateur pour les vérifications d'autorisation ultérieures:
javascript
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
import jwt from "jsonwebtoken";
import { parseSiweMessage } from "viem/siwe";
import { addressMap } from "../cache";
const JWT_SECRET = "your-secret-key"; // Veuillez utiliser une clé plus sécurisée et ajouter les vérifications d'expiration appropriées.
// Vérifier si la valeur du nonce est identique
si (!nonce || nonce !== addressMap.get(address)) {
throw new Error("Invalid nonce");
}
// Vérifier le contenu de la signature
const valid = await publicClient.verifySiweMessage({
message,
adresse,
signature,
});
si (!valid) {
throw new Error("Invalid signature");
}
// Générer un jwt et le retourner
const token = jwt.sign({ address }, JWT_SECRET, { expiresIn: "1h" });
return Response.json({
données : jeton,
});
}
À ce stade, une Dapp de base implémentant la connexion SIWE est développée.
Suggestions d'optimisation
Lors de la connexion SIWE, si vous utilisez le nœud RPC par défaut, le processus de validation peut prendre près de 30 secondes. Il est donc fortement recommandé d'utiliser un service de nœud dédié pour améliorer le temps de réponse de l'interface.
Après avoir obtenu la connexion HTTPS RPC au réseau principal Ethereum, remplacez le RPC par défaut de publicClient dans le code :
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.
15 J'aime
Récompense
15
6
Partager
Commentaire
0/400
AirdropHustler
· Il y a 19h
Eh bien, cette chose est assez courante, je l'ai utilisée tôt.
Voir l'originalRépondre0
FallingLeaf
· Il y a 19h
Signer signifie donner sa vie privée ? Laissez-moi y réfléchir.
Voir l'originalRépondre0
BearMarketMonk
· Il y a 19h
Identification ? Encore une nouvelle astuce pour se faire prendre pour des cons.
Voir l'originalRépondre0
MidnightSnapHunter
· Il y a 19h
La signature n'est qu'une question de plugin.
Voir l'originalRépondre0
Degentleman
· Il y a 19h
Cette fonctionnalité SIWE aurait dû arriver plus tôt, d'accord ?
Guide de mise en œuvre de SIWE : améliorer les fonctionnalités d'authentification des Dapp
SIWE : Comment réaliser l'identification Ethereum pour améliorer les fonctionnalités des Dapps
SIWE(Se connecter avec Ethereum) est une méthode de vérification de l'identification des utilisateurs sur la blockchain Ethereum, similaire à l'initiation d'une transaction par portefeuille, utilisée pour prouver le contrôle de l'utilisateur sur le portefeuille. Le processus d'identification actuel est déjà très simple, il suffit de signer les informations dans le plugin de portefeuille, la plupart des plugins de portefeuille courants sont déjà supportés.
Cet article discute principalement des scénarios de signature sur Ethereum, sans aborder d'autres chaînes publiques comme Solana ou SUI.
Quand devez-vous utiliser SIWE
Si votre Dapp a les besoins suivants, vous pouvez envisager d'utiliser SIWE :
Mais si votre Dapp est principalement une application de requête, comme une application similaire à Ethereum, alors il n'est pas nécessaire d'utiliser SIWE.
Vous pourriez demander, après avoir connecté le portefeuille sur Dapp, n'est-ce pas une preuve de propriété du portefeuille ? Cette affirmation est en partie correcte. Pour le front-end, la connexion du portefeuille indique effectivement l'identification, mais pour les appels API nécessitant un support back-end, il ne suffit pas de transmettre l'adresse, car l'adresse est une information publique, et n'importe qui peut "emprunter".
Principe et processus de SIWE
Le processus de SIWE peut être résumé en trois étapes : connexion au portefeuille - signature - obtention de l'identification. Examinons ces trois étapes en détail.
connecter le portefeuille
C'est une opération Web3 courante qui connecte votre portefeuille dans la Dapp via un plugin de portefeuille.
signature
Les étapes de signature de SIWE comprennent l'obtention de la valeur Nonce, la signature du portefeuille et la vérification de la signature par le backend.
Tout d'abord, il est nécessaire d'appeler l'interface backend pour obtenir la valeur Nonce. Après avoir reçu la demande, le backend générera une valeur Nonce aléatoire et l'associera à l'adresse actuelle, préparant ainsi la signature ultérieure.
Après avoir obtenu la valeur Nonce par le front-end, construisez le contenu de la signature, y compris la valeur Nonce, le nom de domaine, l'ID de la chaîne, le contenu de la signature, etc. En général, une méthode de signature fournie par le portefeuille est utilisée pour signer.
Après avoir construit la signature, envoyez-la au backend.
obtenir l'identification
Après validation de la signature par l'arrière-plan, un identifiant utilisateur correspondant sera renvoyé, tel que JWT. Lors de l'envoi de la demande au backend par le frontend, il suffit d'inclure l'adresse correspondante et l'identification pour prouver la propriété du portefeuille.
Pratique SIWE
Il existe maintenant de nombreux composants et bibliothèques qui prennent en charge la connexion rapide aux portefeuilles et au SIWE. Faisons une opération pratique, l'objectif est de permettre à votre Dapp de renvoyer un JWT pour l'authentification des utilisateurs.
Attention, cet exemple est uniquement utilisé pour présenter le processus de base de SIWE, son utilisation dans un environnement de production peut présenter des problèmes de sécurité.
travaux préparatoires
Nous utilisons Next.js pour développer des applications, et il est nécessaire de préparer l'environnement Node.js. L'avantage d'utiliser Next.js est qu'il permet de développer directement des projets full stack, sans avoir besoin de séparer le front-end et le back-end.
installer les dépendances
Tout d'abord, installez Next.js, exécutez dans le répertoire du projet :
npx create-next-app@14
Après avoir terminé l'installation selon les instructions, accédez au répertoire du projet et démarrez :
npm run dev
Ensuite, accédez à localhost:3000 pour voir le projet Next.js de base en cours d'exécution.
Installer les dépendances liées à SIWE
Nous utilisons Ant Design Web3 pour implémenter SIWE, car il est gratuit, activement maintenu, offre une expérience utilisateur similaire à celle des bibliothèques de composants ordinaires et prend en charge SIWE.
Entrer dans le terminal :
npm install antd @ant-design/web3 @ant-design/web3-wagmi wagmi viem @tanstack/react-query --save
introduire Wagmi
La bibliothèque SIWE d'Ant Design Web3 dépend de Wagmi. Nous avons importé le Provider correspondant dans layout.tsx pour que l'ensemble du projet puisse utiliser les Hooks fournis par Wagmi.
D'abord, définissez la configuration de WagmiProvider :
javascript "use client"; import { getNonce, verifyMessage } from "@/app/api"; import { Mainnet, MetaMask, OkxWallet, TokenPocket, WagmiWeb3ConfigProvider, WalletConnect, } de "@ant-design/web3-wagmi"; import { QueryClient } from "@tanstack/react-query"; importer React de "react"; import { createSiweMessage } from "viem/siwe"; importer { http } de "wagmi"; import { JwtProvider } from "./JwtProvider";
const YOUR_WALLET_CONNECT_PROJECT_ID = "c07c0051c2055890eade3556618e38a6"; const queryClient = new QueryClient();
const WagmiProvider: React.FC = ({ children }) => { const [jwt, setJwt] = React.useState(null);
return ( <wagmiweb3configprovider siwe="{{" getnonce:="" async="" (address)=""> (attendre obtenirNonce(adresse)).données, createMessage: (props) => { return createSiweMessage({ ...props, statement: "Ant Design Web3" }); }, verifyMessage: async (message, signature) => { const jwt = (await verifyMessage(message, signature)).data; setJwt(jwt); return !!jwt; }, }} chains={[Mainnet]} transports={{ [Mainnet.id]: http(), }} walletConnect={{ projectId: YOUR_WALLET_CONNECT_PROJECT_ID, }} portefeuilles={[ MetaMask(), WalletConnect(), TokenPocket({ groupe: "Populaire", }), OkxWallet(), ]} queryClient={queryClient} > {children} ); };
export default WagmiProvider;
Nous utilisons le Provider fourni par Ant Design Web3 et avons défini certaines interfaces SIWE, dont la mise en œuvre sera présentée ultérieurement.
Ensuite, ajoutez un bouton de connexion au portefeuille, en tant qu'entrée de connexion frontale.
À ce stade, nous avons déjà intégré simplement SIWE.
Ensuite, définissez un bouton de connexion pour établir la connexion au portefeuille et signer :
javascript "use client"; importer type { Compte } from "@ant-design/web3"; import { ConnectButton, Connector } from "@ant-design/web3"; import { Flex, Space } from "antd"; importer React de "react"; import { JwtProvider } from "./JwtProvider";
export default function App() { const jwt = React.useContext(JwtProvider);
const renderSignBtnText = ( defaultDom: React.ReactNode, compte?: Compte ) => { const { address } = account ?? {}; const ellipsisAddress = address ? ${address.slice(0, 6)}...${address.slice(-6)} : ""; retournez Connexion en tant que ${ellipsisAddress}; };
return ( <> {(compte) => ( <connectbutton.signin accountcomponent="{false}" renderbuttontext="{(dom)" ==""> renderSignBtnText(dom, account)} /> )} <connectbutton.signin> {jwt} ); }
Ainsi, nous avons réalisé un cadre de connexion SIWE des plus simples.
Implémentation de l'interface
SIWE nécessite certaines interfaces pour aider l'arrière-plan à vérifier l'identification des utilisateurs. Maintenant, réalisons cela simplement.
Nonce
Le nonce est utilisé pour générer un contenu de signature différent à chaque fois que le portefeuille signe, améliorant ainsi la fiabilité. La génération du nonce doit être associée à l'adresse fournie par l'utilisateur afin d'améliorer la précision de la vérification.
L'implémentation du nonce est très directe, tout d'abord, générez une chaîne aléatoire ( composée de lettres et de chiffres ), puis établissez une association entre le nonce et l'adresse :
javascript import { randomBytes } from "crypto"; import { addressMap } from "../cache";
export async function GET(request: Request) { const { searchParams } = new URL(request.url); const address = searchParams.get("address");
si (!adresse) { throw new Error("Adresse invalide"); } const nonce = randomBytes(16).toString("hex"); addressMap.set(address, nonce); return Response.json({ données : nonce, }); }
signMessage
signMessage est utilisé pour signer du contenu, généralement effectué via un plugin de portefeuille, nous avons généralement juste besoin de spécifier la méthode. Dans cet exemple, nous utilisons la méthode de signature de Wagmi.
vérifierMessage
Après que l'utilisateur ait signé, il doit envoyer le contenu avant la signature avec la signature au backend pour vérification. Le backend extrait le contenu de la signature pour comparaison; s'ils correspondent, cela signifie que la vérification est réussie.
De plus, il est nécessaire de vérifier la sécurité du contenu de la signature, par exemple en vérifiant si la valeur Nonce est cohérente avec celle attribuée à l'utilisateur. Une fois la vérification réussie, renvoyez le JWT à l'utilisateur pour les vérifications d'autorisation ultérieures:
javascript import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; import jwt from "jsonwebtoken"; import { parseSiweMessage } from "viem/siwe"; import { addressMap } from "../cache";
const JWT_SECRET = "your-secret-key"; // Veuillez utiliser une clé plus sécurisée et ajouter les vérifications d'expiration appropriées.
const publicClient = createPublicClient({ chaîne : mainnet, transport: http(), });
export async function POST(request: Request) { const { signature, message } = await request.json();
const { nonce, address = "0x" } = parseSiweMessage(message); console.log("nonce", nonce, address, addressMap);
// Vérifier si la valeur du nonce est identique si (!nonce || nonce !== addressMap.get(address)) { throw new Error("Invalid nonce"); }
// Vérifier le contenu de la signature const valid = await publicClient.verifySiweMessage({ message, adresse, signature, });
si (!valid) { throw new Error("Invalid signature"); }
// Générer un jwt et le retourner const token = jwt.sign({ address }, JWT_SECRET, { expiresIn: "1h" }); return Response.json({ données : jeton, }); }
À ce stade, une Dapp de base implémentant la connexion SIWE est développée.
Suggestions d'optimisation
Lors de la connexion SIWE, si vous utilisez le nœud RPC par défaut, le processus de validation peut prendre près de 30 secondes. Il est donc fortement recommandé d'utiliser un service de nœud dédié pour améliorer le temps de réponse de l'interface.
Après avoir obtenu la connexion HTTPS RPC au réseau principal Ethereum, remplacez le RPC par défaut de publicClient dans le code :
javascript const publicClient = createPublicClient({ chaîne : mainnet, transport: http('), //service RPC des nœuds obtenus });
Après le remplacement, le temps de vérification peut être considérablement réduit et la vitesse de l'interface est nettement améliorée.