SIWE (تسجيل الدخول باستخدام Ethereum) هي طريقة للتحقق من هوية المستخدمين على Ethereum، تشبه بدء معاملة المحفظة، لإثبات سيطرة المستخدم على المحفظة. طريقة التحقق الحالية بسيطة للغاية، كل ما عليك هو التوقيع على المعلومات في ملحق المحفظة، وقد دعمت معظم ملحقات المحفظة الشائعة ذلك.
تتناول هذه المقالة مشاهد التوقيع على إيثريوم، ولا تتعلق بسلاسل الكتل الأخرى مثل سولانا، SUI، إلخ.
هل تحتاج إلى SIWE
إذا كانت لديك متطلبات Dapp التالية، يمكنك التفكير في استخدام SIWE:
امتلاك نظام مستخدم خاص به
تحتاج إلى استعلام المعلومات المتعلقة بخصوصية المستخدم
ولكن إذا كان Dapp الخاص بك يركز بشكل رئيسي على وظائف الاستعلام، مثل التطبيقات المشابهة لـ etherscan، يمكنك عدم استخدام SIWE.
قد تتساءل، بعد الاتصال بمحفظة على Dapp، أليس هذا دليلاً على ملكية المحفظة؟ هذا القول صحيح جزئيًا. بالنسبة للواجهة الأمامية، فإن الاتصال بالمحفظة يدل بالفعل على الهوية، لكن بالنسبة لاستدعاءات واجهة البرمجة التي تحتاج إلى دعم خلفي، فإن إرسال العنوان فقط ليس كافيًا، لأن العنوان هو معلومات عامة، ويمكن لأي شخص "استعارة".
مبدأ SIWE وعملية
يمكن تلخيص عملية SIWE في ثلاث خطوات: ربط المحفظة - التوقيع - الحصول على هوية. دعنا نتعرف على هذه الخطوات الثلاث بالتفصيل.
ربط المحفظة
توصيل المحفظة هو إجراء شائع في Web3، من خلال ملحق المحفظة يمكن توصيل المحفظة في Dapp.
توقيع
تتضمن خطوات التوقيع في SIWE الحصول على قيمة Nonce، توقيع المحفظة والتحقق من توقيع الخادم.
يتطلب الحصول على قيمة Nonce استدعاء واجهة برمجة التطبيقات الخلفية. بعد استلام الطلب، ستقوم الخلفية بإنشاء قيمة Nonce عشوائية وربطها بالعنوان الحالي، استعدادًا للتوقيع اللاحق.
بعد الحصول على قيمة Nonce من الواجهة الأمامية، يلزم بناء محتوى التوقيع، والذي يشمل قيمة Nonce، اسم النطاق، معرف السلسلة، ومحتوى التوقيع، وعادةً ما يتم استخدام طريقة التوقيع التي توفرها المحفظة لإجراء التوقيع.
بعد بناء التوقيع، أرسله إلى الخلفية.
الحصول على هوية
بعد التحقق من صحة التوقيع في الواجهة الخلفية، سيتم إرجاع معرف هوية المستخدم، مثل JWT. عند إجراء الطلبات اللاحقة من الواجهة الأمامية، يجب تضمين العنوان المقابل ومعرف الهوية، لإثبات ملكية المحفظة.
ممارسة
توجد العديد من المكونات والمكتبات التي تدعم الاتصال السريع بمحفظة SIWE. هدفنا هو تمكين Dapp من إرجاع JWT للتحقق من هوية المستخدم. لاحظ أن هذا العرض التوضيحي يستخدم فقط لتقديم العملية الأساسية لـ SIWE، وقد توجد مشكلات أمان عند الاستخدام في بيئة الإنتاج.
الأعمال التحضيرية
تستخدم هذه المقالة Next.js لتطوير التطبيقات، وتتطلب بيئة Node.js. من فوائد استخدام Next.js هو أنه يمكنك تطوير مشاريع كاملة في الواجهة الخلفية والواجهة الأمامية دون الحاجة إلى تقسيمها إلى مشروعين.
تثبيت الاعتماديات
أولاً، قم بتثبيت Next.js، نفذ في دليل المشروع:
نحن نستخدم الأمر npx create-next-app@14
بعد إتمام التثبيت حسب التعليمات، انتقل إلى دليل المشروع وشغل:
npm تشغيل dev
وفقًا للتعليمات الموجودة في الطرفية، يمكنك زيارة localhost:3000 لرؤية مشروع Next.js الأساسي.
تثبيت التبعيات المتعلقة بـ SIWE
SIWE يحتاج إلى نظام تسجيل دخول، لذلك يتطلب الاتصال بمحفظة. هنا نستخدم Ant Design Web3، لأن:
مجاني تمامًا ويتم صيانته بنشاط
كمكتبة مكونات Web3، فإن تجربة الاستخدام مشابهة لمكتبات المكونات العادية، دون أي عبء عقلي إضافي.
يعتمد SIWE في Ant Design Web3 على مكتبة Wagmi. نحتاج إلى استيراد موفرات ذات الصلة في layout.tsx، حتى يتمكن المشروع بأكمله من استخدام Hooks المقدمة من Wagmi.
أولاً، قم بتعريف إعدادات WagmiProvider:
جافا سكريبت
"استخدم العميل";
استيراد { الحصول على nonce، التحقق من الرسالة } من "@/app/api"؛
استيراد {
الشبكة الرئيسية،
ميتا ماسك،
محفظة Okx
توكن بوكيت,
WagmiWeb3ConfigProvider,
WalletConnect،
} من "@ant-design/web3-wagmi";
import { QueryClient } من "@tanstack/react-query" ؛
استيراد React من "react";
import { createSiweMessage } من "viem / siwe" ؛
استيراد { http } من "wagmi"؛
استيراد { JwtProvider } من "./JwtProvider" ؛
ثم أضف زر الاتصال بالمحفظة، وبذلك تم إضافة مدخل الاتصال في الواجهة الأمامية. وبذلك، تم دمج SIWE، والخطوات بسيطة جداً.
بعد ذلك، قم بتعريف زر الاتصال، لتنفيذ اتصال المحفظة والتوقيع:
جافا سكريبت
"استخدم العميل";
استيراد النوع { الحساب } من "@ant-design/web3";
استيراد { ConnectButton ، Connector } من "@ant-design / web3" ؛
استيراد { مرونة ، مساحة } من "antd"؛
استيراد React من "react";
استيراد { JwtProvider } من "./JwtProvider" ؛
تصدير وظيفة افتراضية App() {
const jwt = React.useContext(JwtProvider);
const renderSignBtnText = (
defaultDom: React.ReactNode ،
الحساب؟: حساب
) => {
const { address } = حساب ؟؟ {};
const ellipsisAddress = العنوان
? ${address.slice(0, 6)}...${address.slice(-6)}
: "";
العودة لتسجيل الدخول كـ ${ellipsisAddress};
};
( الإرجاع
<>
<flex vertical="" فجوة ="كبير">
{JWT}
);
}
بهذه الطريقة تم تحقيق أبسط إطار تسجيل دخول SIWE.
تنفيذ الواجهة
تحتاج SIWE إلى بعض الواجهات لمساعدة الخلفية في التحقق من هوية المستخدم. الآن دعنا ننفذ ذلك ببساطة.
العشوائي
Nonce يستخدم لجعل المحتوى الذي يتم إنشاؤه عند توقيع المحفظة يتغير في كل مرة، مما يزيد من موثوقية التوقيع. يتطلب توليد Nonce أن يرتبط بعنوان المستخدم المدخل، مما يعزز دقة التحقق.
إن تطبيق Nonce مباشر جدًا، أولاً يتم إنشاء سلسلة عشوائية ( تتكون من أحرف وأرقام )، ثم يتم ربط nonce و address:
جافا سكريبت
استيراد { randomBytes } من "التشفير" ؛
استيراد { addressMap } من "../cache";
تصدير الدالة غير المتزامنة GET(request: Request) {
const { searchParams } = عنوان URL الجديد(request.url);
const address = searchParams.get( "address");
إذا (!address) {
throw new Error("عنوان غير صالح");
}
const nonce = randomBytes(16).toString("hex");
addressMap.set(العنوان, nonce);
إرجاع Response.json({
البيانات: nonce,
});
}
توقيع الرسالة
signMessage تُستخدم لتوقيع المحتوى، وغالبًا ما يتم تنفيذ هذه الوظيفة بواسطة مكون إضافي للمحفظة، وعادةً لا نحتاج إلى تكوينها، يكفي فقط تحديد الطريقة. في هذا العرض التوضيحي، نستخدم طريقة التوقيع من Wagmi.
تحقق من الرسالة
بعد توقيع المستخدم، يجب إرسال المحتوى الذي تم التوقيع عليه مع التوقيع إلى الخلفية للتحقق. يقوم الخادم بتحليل التوقيع لاستخراج المحتوى المقابل للمقارنة، وإذا كان متطابقًا، فهذا يعني أن التحقق قد نجح.
بالإضافة إلى ذلك، يجب إجراء تحقق من أمان محتوى التوقيع، مثل ما إذا كانت قيمة Nonce في محتوى التوقيع تتوافق مع تلك التي تم توزيعها على المستخدمين. بعد اجتياز التحقق، يجب إعادة JWT للمستخدم لاستخدامه في التحقق من الأذونات لاحقًا، الكود النموذجي كما يلي:
جافا سكريبت
import { createPublicClient, http } من "viem";
استيراد { الشبكة الرئيسية } من "viem/chains";
استيراد jwt من "jsonwebtoken";
import { parseSiweMessage } من "viem / siwe" ؛
استيراد { addressMap } من "../cache"؛
const JWT_SECRET = "your-secret-key"; // يرجى استخدام مفتاح أكثر أمانًا وإضافة التحقق من انتهاء الصلاحية المناسب وما إلى ذلك
const publicClient = createPublicClient({
سلسلة: الشبكة الرئيسية,
النقل: http(),
});
تصدير وظيفة غير متزامنة POST(request: طلب) {
const { signature, message } = await request.json();
حتى الآن، تم تطوير Dapp لتنفيذ تسجيل الدخول SIWE الأساسي.
اقتراحات تحسين
قد يتطلب التحقق من تسجيل الدخول باستخدام SIWE عبر عقدة RPC الافتراضية ما يقرب من 30 ثانية، لذا يُنصح بشدة باستخدام خدمة عقدة مخصصة لتحسين وقت استجابة واجهة البرمجة. تستخدم هذه المقالة خدمة العقدة من ZAN، ويمكن الحصول على اتصال RPC المناسب من وحدة التحكم في خدمة عقدة ZAN.
بعد الحصول على اتصال HTTPS RPC لشبكة Ethereum الرئيسية، استبدل RPC الافتراضي لـ publicClient في الكود:
جافا سكريبت
const publicClient = createPublicClient({
السلسلة: الشبكة الرئيسية,
النقل: http('), // تم الحصول على خدمة RPC لجدول ZAN
});
بعد الاستبدال، ستنخفض مدة التحقق بشكل ملحوظ، وستتسارع سرعة الواجهة بشكل واضح.
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
تكنولوجيا SIWE تعزز التحقق من هوية المستخدم في Dapp
SIWE: التقنية الأساسية لتحسين وظائف Dapp
SIWE (تسجيل الدخول باستخدام Ethereum) هي طريقة للتحقق من هوية المستخدمين على Ethereum، تشبه بدء معاملة المحفظة، لإثبات سيطرة المستخدم على المحفظة. طريقة التحقق الحالية بسيطة للغاية، كل ما عليك هو التوقيع على المعلومات في ملحق المحفظة، وقد دعمت معظم ملحقات المحفظة الشائعة ذلك.
تتناول هذه المقالة مشاهد التوقيع على إيثريوم، ولا تتعلق بسلاسل الكتل الأخرى مثل سولانا، SUI، إلخ.
هل تحتاج إلى SIWE
إذا كانت لديك متطلبات Dapp التالية، يمكنك التفكير في استخدام SIWE:
ولكن إذا كان Dapp الخاص بك يركز بشكل رئيسي على وظائف الاستعلام، مثل التطبيقات المشابهة لـ etherscan، يمكنك عدم استخدام SIWE.
قد تتساءل، بعد الاتصال بمحفظة على Dapp، أليس هذا دليلاً على ملكية المحفظة؟ هذا القول صحيح جزئيًا. بالنسبة للواجهة الأمامية، فإن الاتصال بالمحفظة يدل بالفعل على الهوية، لكن بالنسبة لاستدعاءات واجهة البرمجة التي تحتاج إلى دعم خلفي، فإن إرسال العنوان فقط ليس كافيًا، لأن العنوان هو معلومات عامة، ويمكن لأي شخص "استعارة".
مبدأ SIWE وعملية
يمكن تلخيص عملية SIWE في ثلاث خطوات: ربط المحفظة - التوقيع - الحصول على هوية. دعنا نتعرف على هذه الخطوات الثلاث بالتفصيل.
ربط المحفظة
توصيل المحفظة هو إجراء شائع في Web3، من خلال ملحق المحفظة يمكن توصيل المحفظة في Dapp.
توقيع
تتضمن خطوات التوقيع في SIWE الحصول على قيمة Nonce، توقيع المحفظة والتحقق من توقيع الخادم.
يتطلب الحصول على قيمة Nonce استدعاء واجهة برمجة التطبيقات الخلفية. بعد استلام الطلب، ستقوم الخلفية بإنشاء قيمة Nonce عشوائية وربطها بالعنوان الحالي، استعدادًا للتوقيع اللاحق.
بعد الحصول على قيمة Nonce من الواجهة الأمامية، يلزم بناء محتوى التوقيع، والذي يشمل قيمة Nonce، اسم النطاق، معرف السلسلة، ومحتوى التوقيع، وعادةً ما يتم استخدام طريقة التوقيع التي توفرها المحفظة لإجراء التوقيع.
بعد بناء التوقيع، أرسله إلى الخلفية.
الحصول على هوية
بعد التحقق من صحة التوقيع في الواجهة الخلفية، سيتم إرجاع معرف هوية المستخدم، مثل JWT. عند إجراء الطلبات اللاحقة من الواجهة الأمامية، يجب تضمين العنوان المقابل ومعرف الهوية، لإثبات ملكية المحفظة.
ممارسة
توجد العديد من المكونات والمكتبات التي تدعم الاتصال السريع بمحفظة SIWE. هدفنا هو تمكين Dapp من إرجاع JWT للتحقق من هوية المستخدم. لاحظ أن هذا العرض التوضيحي يستخدم فقط لتقديم العملية الأساسية لـ SIWE، وقد توجد مشكلات أمان عند الاستخدام في بيئة الإنتاج.
الأعمال التحضيرية
تستخدم هذه المقالة Next.js لتطوير التطبيقات، وتتطلب بيئة Node.js. من فوائد استخدام Next.js هو أنه يمكنك تطوير مشاريع كاملة في الواجهة الخلفية والواجهة الأمامية دون الحاجة إلى تقسيمها إلى مشروعين.
تثبيت الاعتماديات
أولاً، قم بتثبيت Next.js، نفذ في دليل المشروع:
نحن نستخدم الأمر npx create-next-app@14
بعد إتمام التثبيت حسب التعليمات، انتقل إلى دليل المشروع وشغل:
npm تشغيل dev
وفقًا للتعليمات الموجودة في الطرفية، يمكنك زيارة localhost:3000 لرؤية مشروع Next.js الأساسي.
تثبيت التبعيات المتعلقة بـ SIWE
SIWE يحتاج إلى نظام تسجيل دخول، لذلك يتطلب الاتصال بمحفظة. هنا نستخدم Ant Design Web3، لأن:
قم بالتنفيذ في الطرفية:
npm تثبيت antd @ant-design/web3 @ant-design/web3-wagmi wagmi viem @tanstack/react-query --save
تقديم Wagmi
يعتمد SIWE في Ant Design Web3 على مكتبة Wagmi. نحتاج إلى استيراد موفرات ذات الصلة في layout.tsx، حتى يتمكن المشروع بأكمله من استخدام Hooks المقدمة من Wagmi.
أولاً، قم بتعريف إعدادات WagmiProvider:
جافا سكريبت "استخدم العميل"; استيراد { الحصول على nonce، التحقق من الرسالة } من "@/app/api"؛ استيراد { الشبكة الرئيسية، ميتا ماسك، محفظة Okx توكن بوكيت, WagmiWeb3ConfigProvider, WalletConnect، } من "@ant-design/web3-wagmi"; import { QueryClient } من "@tanstack/react-query" ؛ استيراد React من "react"; import { createSiweMessage } من "viem / siwe" ؛ استيراد { http } من "wagmi"؛ استيراد { JwtProvider } من "./JwtProvider" ؛
const YOUR_WALLET_CONNECT_PROJECT_ID = "c07c0051c2055890eade3556618e38a6"; const queryClient = QueryClient() جديد;
const WagmiProvider: React.FC = ({ children }) = > { const [jwt, setJwt] = React.useState(null);
( الإرجاع <wagmiweb3configprovider siweconfig="{{" getnonce:="" async="" (address)=""> (انتظر الحصول على nonce(عنوان)).البيانات, createMessage: (props) => { العودة createSiweMessage( { ... الدعائم ، بيان: "Ant Design Web3" }); }, verifyMessage: (message غير متزامن، signature) = > { const jwt = (await verifyMessage(message, signature)).data; setJwt(jwt). أعاد!! JWT. }, }} السلاسل = {[Mainnet]} transports={{ [Mainnet.id]: http()، }} walletConnect={{ معرف المشروع: YOUR_WALLET_CONNECT_PROJECT_ID ، }} المحافظ = {[ ميتا ماسك(), WalletConnect()، توكن بوكت({ المجموعة: "شائع" ، }), OkxWallet()، ]} queryClient={queryClient} > {أطفال} ); };
تصدير افتراضي WagmiProvider;
ثم أضف زر الاتصال بالمحفظة، وبذلك تم إضافة مدخل الاتصال في الواجهة الأمامية. وبذلك، تم دمج SIWE، والخطوات بسيطة جداً.
بعد ذلك، قم بتعريف زر الاتصال، لتنفيذ اتصال المحفظة والتوقيع:
جافا سكريبت "استخدم العميل"; استيراد النوع { الحساب } من "@ant-design/web3"; استيراد { ConnectButton ، Connector } من "@ant-design / web3" ؛ استيراد { مرونة ، مساحة } من "antd"؛ استيراد React من "react"; استيراد { JwtProvider } من "./JwtProvider" ؛
تصدير وظيفة افتراضية App() { const jwt = React.useContext(JwtProvider);
const renderSignBtnText = ( defaultDom: React.ReactNode ، الحساب؟: حساب ) => { const { address } = حساب ؟؟ {}; const ellipsisAddress = العنوان ? ${address.slice(0, 6)}...${address.slice(-6)} : ""; العودة لتسجيل الدخول كـ ${ellipsisAddress}; };
( الإرجاع <> <flex vertical="" فجوة ="كبير">
بهذه الطريقة تم تحقيق أبسط إطار تسجيل دخول SIWE.
تنفيذ الواجهة
تحتاج SIWE إلى بعض الواجهات لمساعدة الخلفية في التحقق من هوية المستخدم. الآن دعنا ننفذ ذلك ببساطة.
العشوائي
Nonce يستخدم لجعل المحتوى الذي يتم إنشاؤه عند توقيع المحفظة يتغير في كل مرة، مما يزيد من موثوقية التوقيع. يتطلب توليد Nonce أن يرتبط بعنوان المستخدم المدخل، مما يعزز دقة التحقق.
إن تطبيق Nonce مباشر جدًا، أولاً يتم إنشاء سلسلة عشوائية ( تتكون من أحرف وأرقام )، ثم يتم ربط nonce و address:
جافا سكريبت استيراد { randomBytes } من "التشفير" ؛ استيراد { addressMap } من "../cache";
تصدير الدالة غير المتزامنة GET(request: Request) { const { searchParams } = عنوان URL الجديد(request.url); const address = searchParams.get( "address");
إذا (!address) { throw new Error("عنوان غير صالح"); } const nonce = randomBytes(16).toString("hex"); addressMap.set(العنوان, nonce); إرجاع Response.json({ البيانات: nonce, }); }
توقيع الرسالة
signMessage تُستخدم لتوقيع المحتوى، وغالبًا ما يتم تنفيذ هذه الوظيفة بواسطة مكون إضافي للمحفظة، وعادةً لا نحتاج إلى تكوينها، يكفي فقط تحديد الطريقة. في هذا العرض التوضيحي، نستخدم طريقة التوقيع من Wagmi.
تحقق من الرسالة
بعد توقيع المستخدم، يجب إرسال المحتوى الذي تم التوقيع عليه مع التوقيع إلى الخلفية للتحقق. يقوم الخادم بتحليل التوقيع لاستخراج المحتوى المقابل للمقارنة، وإذا كان متطابقًا، فهذا يعني أن التحقق قد نجح.
بالإضافة إلى ذلك، يجب إجراء تحقق من أمان محتوى التوقيع، مثل ما إذا كانت قيمة Nonce في محتوى التوقيع تتوافق مع تلك التي تم توزيعها على المستخدمين. بعد اجتياز التحقق، يجب إعادة JWT للمستخدم لاستخدامه في التحقق من الأذونات لاحقًا، الكود النموذجي كما يلي:
جافا سكريبت import { createPublicClient, http } من "viem"; استيراد { الشبكة الرئيسية } من "viem/chains"; استيراد jwt من "jsonwebtoken"; import { parseSiweMessage } من "viem / siwe" ؛ استيراد { addressMap } من "../cache"؛
const JWT_SECRET = "your-secret-key"; // يرجى استخدام مفتاح أكثر أمانًا وإضافة التحقق من انتهاء الصلاحية المناسب وما إلى ذلك
const publicClient = createPublicClient({ سلسلة: الشبكة الرئيسية, النقل: http(), });
تصدير وظيفة غير متزامنة POST(request: طلب) { const { signature, message } = await request.json();
const { nonce ، العنوان = "0x" } = parseSiweMessage(message) ؛ console.log( "nonce" ، nonce ، العنوان ، addressMap) ؛
// تحقق مما إذا كانت قيمة nonce متطابقة إذا (!nonce || nonce !== addressMap.get(address)) { رمي Error( جديد "غير صالح") ؛ }
// التحقق من محتوى التوقيع const valid = await publicClient.verifySiweMessage({ رسالة, العنوان، توقيع, });
إذا (!valid) { throw new Error("توقيع غير صالح"); }
// إنشاء jwt وإرجاعه رمز const = jwt.sign({ address }, JWT_SECRET, { expiresIn: "1h" }); إرجاع Response.json({ بيانات: توكن, }); }
حتى الآن، تم تطوير Dapp لتنفيذ تسجيل الدخول SIWE الأساسي.
اقتراحات تحسين
قد يتطلب التحقق من تسجيل الدخول باستخدام SIWE عبر عقدة RPC الافتراضية ما يقرب من 30 ثانية، لذا يُنصح بشدة باستخدام خدمة عقدة مخصصة لتحسين وقت استجابة واجهة البرمجة. تستخدم هذه المقالة خدمة العقدة من ZAN، ويمكن الحصول على اتصال RPC المناسب من وحدة التحكم في خدمة عقدة ZAN.
بعد الحصول على اتصال HTTPS RPC لشبكة Ethereum الرئيسية، استبدل RPC الافتراضي لـ publicClient في الكود:
جافا سكريبت const publicClient = createPublicClient({ السلسلة: الشبكة الرئيسية, النقل: http('), // تم الحصول على خدمة RPC لجدول ZAN });
بعد الاستبدال، ستنخفض مدة التحقق بشكل ملحوظ، وستتسارع سرعة الواجهة بشكل واضح.