Hướng dẫn sử dụng SIWE: Làm cách nào để Dapp của bạn mạnh hơn?

avatar
PANews
12-31
Bài viết này được dịch máy
Xem bản gốc
Dưới đây là bản dịch tiếng Việt của nội dung được cung cấp, với các từ đã được dịch theo yêu cầu:

Bài giới thiệu này tuân theo quy tắc EIP-4361 Sign-In with Ethereum

SIWE (Sign-In with Ethereum) là một cách xác minh danh tính người dùng trên Ethereum, tương tự như khởi tạo một giao dịch bằng ví, để chứng minh người dùng có quyền kiểm soát ví đó.

Hiện nay, cách xác thực danh tính đã rất đơn giản, chỉ cần ký vào thông tin trong plugin ví là được, hầu hết các plugin ví phổ biến đều đã hỗ trợ tính năng này.

Bài viết này xem xét kịch bản ký trên Ethereum, các nền tảng khác như Solana, Sui, v.v. không nằm trong phạm vi thảo luận.

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Dự án của bạn có cần SIWE không

SIWE được thiết kế để giải quyết vấn đề xác minh danh tính bằng địa chỉ ví, vì vậy nếu bạn có những yêu cầu sau, hãy cân nhắc sử dụng SIWE:

    • Dapp của bạn có hệ thống người dùng riêng;
    • Cần truy vấn thông tin liên quan đến quyền riêng tư của người dùng;

Tuy nhiên, nếu Dapp của bạn chủ yếu là chức năng tra cứu, như ứng dụng etherscan, thì không cần SIWE cũng được.

Bạn có thể có một câu hỏi, sau khi kết nối ví trên Dapp, không phải là tôi đã sở hữu toàn bộ ví đó rồi sao?

Đúng vậy, nhưng không hoàn toàn. Đối với mặt trước, việc kết nối ví đúng là bạn đã xác nhận danh tính của mình, nhưng đối với một số API cần hỗ trợ từ phía sau, bạn vẫn không thể chứng minh danh tính của mình, nếu chỉ truyền địa chỉ của bạn, thì bất kỳ ai cũng có thể "mượn" danh tính của bạn, vì địa chỉ là thông tin công khai.

Nguyên lý và quy trình của SIWE

Quy trình SIWE tóm tắt thành 3 bước: Kết nối ví -- Ký -- Lấy định danh.

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Kết nối ví

Kết nối ví là một thao tác WEB3 phổ biến, có thể kết nối ví của bạn với Dapp thông qua plugin ví.

Trong SIWE, bước ký bao gồm lấy giá trị Nonce, ký bằng ví và xác minh chữ ký ở phía sau.

Việc lấy giá trị Nonce nên tham khảo thiết kế của Nonce trong giao dịch ETH, cũng cần gọi API ở phía sau để lấy. Phía sau khi nhận được yêu cầu, sẽ tạo ra một giá trị Nonce ngẫu nhiên và liên kết với địa chỉ hiện tại, để chuẩn bị cho việc ký sau này.

Sau khi lấy được giá trị Nonce, phía trước cần xây dựng nội dung ký, SIWE có thể thiết kế nội dung ký bao gồm giá trị Nonce đã lấy, tên miền, ID chuỗi, nội dung ký, v.v., chúng ta thường sử dụng phương thức ký do ví cung cấp để ký nội dung này.

Sau khi xây dựng xong chữ ký, cuối cùng gửi chữ ký này cho phía sau.

Lấy định danh

Phía sau sau khi xác minh chữ ký và thông qua, sẽ trả về định danh người dùng tương ứng, có thể là JWT, phía trước sau đó khi gửi yêu cầu cho phía sau, kèm theo địa chỉ và định danh này, sẽ có thể chứng minh quyền sở hữu ví.

Thực hành

Hiện nay đã có rất nhiều thành phần, thư viện hỗ trợ nhà phát triển nhanh chóng tích hợp kết nối ví và SIWE, chúng ta có thể thực hành một chút, mục tiêu là để Dapp của bạn có thể trả về JWT để xác minh danh tính người dùng.

Lưu ý, DEMO này chỉ nhằm mục đích giới thiệu quy trình cơ bản của SIWE, sử dụng trong môi trường sản xuất có thể sẽ có vấn đề về bảo mật.

Chuẩn bị trước

Bài viết này sử dụng cách phát triển ứng dụng bằng nextjs, vì vậy cần chuẩn bị sẵn môi trường nodejs. Sử dụng nextjs là một lợi thế, vì chúng ta có thể trực tiếp phát triển dự án full-stack, không cần tách thành dự án front-end và back-end riêng biệt.

Cài đặt các phụ thuộc

Đầu tiên chúng ta cài đặt nextjs, trong thư mục dự án của bạn, nhập lệnh trong dòng lệnh:

npx create-next-app@14

Làm theo hướng dẫn để cài đặt nextjs, bạn sẽ thấy nội dung sau:

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Sau khi vào thư mục dự án, bạn sẽ thấy giàn giáo nextjs đã giúp chúng ta làm rất nhiều công việc. Chúng ta có thể chạy dự án trong thư mục này:

npm run dev

Sau đó theo hướng dẫn của terminal, truy cập localhost: 3000 và bạn sẽ thấy một dự án nextjs cơ bản đã chạy.

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Cài đặt các phụ thuộc liên quan đến SIWE

Dựa trên giới thiệu trước đó, SIWE cần một hệ thống đăng nhập, vì vậy chúng ta cần kết nối dự án với ví, ở đây chúng ta sử dụng Ant Design Web3 (https://web3.ant.design/), vì:

  1. Hoàn toàn miễn phí và hiện đang được bảo trì tích cực
  2. Là thư viện WEB3 component, cách sử dụng tương tự như các thư viện component thông thường, không có gánh nặng về nhận thức
  3. Và hỗ trợ SIWE.

Chúng ta cần nhập lệnh trong terminal:

npm install antd @ant-design/web3 @ant-design/web3-wagmi wagmi viem @tanstack/react-query --save 

Nhập Wagmi

SIWE của Ant Design Web3 dựa trên thư viện Wagmi để thực hiện, vì vậy trong dự án cần nhập các component tương ứng. Chúng tôi sẽ nhập Provider của Wagmi trong layout.tsx, để toàn bộ dự án có thể sử dụng các Hook do Wagmi cung cấp.

Đầu tiên chúng ta định nghĩa cấu hình của WagmiProvider, mã như sau:

"use client";import { getNonce, verifyMessage } from "@/app/api";import {Mainnet,MetaMask,OkxWallet,TokenPocket,WagmiWeb3ConfigProvider,WalletConnect,} from "@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 = new QueryClient();const WagmiProvider: React.FC = ({ children }) => {const [jwt, setJwt] = React.useState(null);return ((await getNonce(address)).data,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,}}wallets={[MetaMask(),WalletConnect(),TokenPocket({group: "Popular",}),OkxWallet(),]}queryClient={queryClient}>{children});};export default WagmiProvider;

Chúng tôi sử dụng Provider do Ant Design Web3 cung cấp, và định nghĩa một số API liên quan đến SIWE, cách triển khai cụ thể các API này sẽ được giới thiệu sau.

Sau đó chúng tôi sẽ nhập nút kết nối ví, để có thể thêm một điểm truy cập kết nối vào giao diện trước.

Đến đây, việc tích hợp SIWE đã hoàn tất, các bước rất đơn giản.

Tiếp theo chúng tôi cần định nghĩa một nút kết nối để thực hiện kết nối ví và ký, mã như sau:

"use client";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 function App() {const jwt = React.useContext(JwtProvider);const renderSignBtnText = (defaultDom: React.ReactNode,account?: Account) => {const { address } = account ?? {};const ellipsisAddress = address? `${address.slice(0, 6)}...${address.slice(-6)}`: "";return `Sign in as ${ellipsisAddress}`;};return (<>

{jwt}

);}

Như vậy chúng ta đã triển khai một khung đăng nhập SIWE cơ bản.

Triển khai API

Theo giới thiệu trên, SIWE cần một số API để giúp phía sau xác minh danh tính người dùng. Bây giờ chúng ta sẽ triển khai một số API đơn giản.

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");if (!address) {throw new Error("Invalid address");}const nonce = randomBytes(16).toString("hex");addressMap.set(address, nonce);return Response.json({data: nonce,});}

Ký nhắn tin

Chức năng của ký nhắn tin là ký nội dung, phần chức năng này thường được thực hiện thông qua plugin ví, chúng ta thường không cần phải cấu hình, chỉ cần chỉ định phương thức là được, trong Demo này chúng ta sử dụng phương thức ký của Wagmi.

Xác minh nhắn tin

Sau khi người dùng ký nội dung, cần gửi nội dung trước khi ký và chữ ký cho backend để xác minh, backend sẽ giải mã chữ ký để so sánh nội dung, nếu khớp thì xác minh thành công.

Ngoài ra, đối với nội dung ký còn cần phải kiểm tra một số vấn đề về bảo mật, chẳng hạn như giá trị Nonce trong nội dung ký có khớp với giá trị chúng ta cấp cho người dùng hay không. Sau khi xác minh thành công, cần trả về JWT tương ứng của người dùng để kiểm tra quyền truy cập sau này, ví dụ mã như sau:

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"; // Vui lòng sử dụng khóa bí mật an toàn hơn và thêm kiểm tra hết hạn tương ứngconst publicClient = createPublicClient({chain: 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);// Kiểm tra giá trị Nonce có khớp khôngif (!nonce || nonce !== addressMap.get(address)) {throw new Error("Invalid nonce");}// Kiểm tra chữ ký nội dungconst valid = await publicClient.verifySiweMessage({message,address,signature,});if (!valid) {throw new Error("Invalid signature");}// Tạo JWT và trả vềconst token = jwt.sign({ address }, JWT_SECRET, { expiresIn: "1h" });return Response.json({data: token,});}

Như vậy, một Dapp cơ bản thực hiện đăng nhập SIWE đã hoàn thành.

Một số mục tiêu tối ưu

Hiện tại khi chúng ta thực hiện đăng nhập SIWE, nếu sử dụng nút RPC mặc định thì quá trình xác minh sẽ mất khoảng 30 giây, vì vậy ở đây chúng tôi rất khuyến khích sử dụng dịch vụ nút chuyên dụng để tăng tốc độ phản hồi của API. Bài viết này sử dụng dịch vụ nút của ZAN (https://zan.top/home/node-service?chInfo=ch_WZ), bạn có thể truy cập vào bảng điều khiển dịch vụ nút ZAN để lấy RPC tương ứng.

Hướng dẫn sử dụng SIWE: Làm thế nào để Dapp của bạn trở nên mạnh mẽ hơn?

Sau khi có được HTTPS RPC của mạng chủ Ethereum, hãy thay thế RPC mặc định của publicClient trong mã:

const publicClient = createPublicClient({chain: mainnet,transport: http('https://api.zan.top/node/v1/eth/mainnet/xxxx'), //RPC dịch vụ nút ZAN đã lấy});

Sau khi thay thế, thời gian xác minh có thể giảm đáng kể, tốc độ API sẽ tăng lên đáng kể.

Nguồn
Tuyên bố từ chối trách nhiệm: Nội dung trên chỉ là ý kiến của tác giả, không đại diện cho bất kỳ lập trường nào của Followin, không nhằm mục đích và sẽ không được hiểu hay hiểu là lời khuyên đầu tư từ Followin.
Thích
Thêm vào Yêu thích
Bình luận