שילוב MetaMask לכניסת Web3 באתר שלך
המשתמשים עייפים מסיסמאות. כל חודש מביא עמו עשרות דליפות מסדי נתונים עם סיסמאות מהונדסות, והתקפות דיוג הופכות למתוחכמות יותר. MetaMask מותקן על מיליוני מכשירים, אך רוב האתרים עדיין דורשים הרשמה עם אישור דוא"ל. למה לא לתת למשתמשים להיכנס עם הארנק שלהם? יישמנו פתרון Web3 Login באמצעות React + Node.js — ללא סיסמאות, אפס אמון בנתוני משתמש, והגנה מפני התקפות replay.
תארו לעצמכם: משתמש מבקר באתר שלכם, לוחץ על "התחבר עם MetaMask", חותם על הודעה — והוא בפנים. ללא מילוי טפסים, ללא מיילי אישור. מניסיוננו, שיעור ההמרה לאימות כזה מגיע ל-90%, שזה גבוה ב-30% מטופס התחברות רגיל. עומס התשתית גם יורד: אין עוד צורך לאחסן גיבובי סיסמאות, לטפל באיפוסי סיסמאות, או להתגונן מפני התקפות כוח גס. עלויות תחזוקת האימות יכולות לרדת בעד 50%.
איך עובדת כניסה דרך MetaMask?
המנגנון פשוט: המשתמש חותם על הודעה עם המפתח הפרטי שלו, השרת משחזר את הכתובת ומנפיק JWT. ללא סיסמאות, ללא מסד נתוני משתמשים — רק כתובת הארנק.
- הפרונטאנד מבקש
nonceמהשרת עבור כתובת הארנק. - MetaMask מבקש מהמשתמש לחתום על ההודעה.
- המשתמש חותם — MetaMask מחזיר את החתימה.
- השרת מאמת את החתימה ומנפיק JWT.
למה לוותר על סיסמאות?
| קריטריון | התחברות מסורתית (דוא"ל + סיסמה) | Web3 Login (MetaMask) |
|---|---|---|
| אבטחה | תלוי בחוזק הסיסמה, פגיע לדיוג | חתימה מבוססת מפתח, דיוג חסר תועלת ללא גישה לארנק |
| חוויית משתמש | הרשמה, אישור דוא"ל, איפוס סיסמה | קליק אחד, ללא צורך לזכור |
| עלות תמיכה | אחסון גיבובי סיסמאות, איפוסי סיסמאות, הגנה מפני כוח גס | רק nonce + אימות, עומס נמוך יותר |
Web3 Login מהיר פי 3 בהמרה — משתמשים לא נוטשים את הטופס בשלב הראשון. ethers.js הוא הכלי העיקרי לטיפול בחתימות.
למה Nonce הכרחי לאבטחה?
ללא nonce, ניתן ליירט חתימה ולשחזר אותה. ה-nonce הוא מספר אקראי חד-פעמי שנוצר על ידי השרת וחייב להיות חלק מההודעה החתומה. לאחר אימות מוצלח, ה-nonce מוסר מהאחסון (Redis עם TTL של 5 דקות). גם אם תוקף ישיג את החתימה, לא ניתן יהיה להשתמש בה שוב. זהו מנגנון הגנה סטנדרטי המתואר ב-EIP-712.
איך להגן על ה-API מפני שחזור חתימה?
בנוסף, ניתן לחסום שימוש חוזר באותה חתימה לפי ה-hash שלה. אנו מאחסנים את hash החתימה ב-Redis למשך תקופת ה-TTL של ה-nonce. אם חתימה כבר הייתה בשימוש, הבקשה נדחית. זה מגן מפני מצבי מרוץ בבקשות מקבילות.
פרונטאנד: חיבור MetaMask
import { ethers } from 'ethers';
async function loginWithMetaMask(): Promise<void> {
// 1. Проверить наличие MetaMask
if (!window.ethereum) {
throw new Error('MetaMask не установлен');
}
// 2. Запросить доступ к аккаунтам
const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send('eth_requestAccounts', []);
const signer = await provider.getSigner();
const address = await signer.getAddress();
// 3. Получить nonce от сервера
const nonceResponse = await fetch(`/api/auth/nonce?address=${address}`);
const { nonce } = await nonceResponse.json();
// 4. Подписать сообщение
const message = `Войти на example.com\n\nNonce: ${nonce}\nTime: ${new Date().toISOString()}`;
const signature = await signer.signMessage(message);
// 5. Отправить подпись серверу
const authResponse = await fetch('/api/auth/web3', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ address, signature, message })
});
const { token } = await authResponse.json();
localStorage.setItem('auth_token', token);
} בקאנד: אימות חתימה
// Node.js + ethers.js
import { ethers } from 'ethers';
import { randomBytes } from 'crypto';
// Хранение nonce (Redis с TTL 5 мин)
async function getNonce(address: string): Promise<string> {
const normalized = address.toLowerCase();
const existing = await redis.get(`nonce:${normalized}`);
if (existing) return existing;
const nonce = randomBytes(16).toString('hex');
await redis.setex(`nonce:${normalized}`, 300, nonce);
return nonce;
}
// Верификация
async function verifyWeb3Auth(req, res) {
const { address, signature, message } = req.body;
const normalized = address.toLowerCase();
// Проверить nonce в сообщении
const storedNonce = await redis.get(`nonce:${normalized}`);
if (!storedNonce || !message.includes(storedNonce)) {
return res.status(401).json({ error: 'Invalid or expired nonce' });
}
// Восстановить адрес из подписи
const recoveredAddress = ethers.verifyMessage(message, signature).toLowerCase();
if (recoveredAddress !== normalized) {
return res.status(401).json({ error: 'Signature verification failed' });
}
// Удалить использованный nonce
await redis.del(`nonce:${normalized}`);
// Найти или создать пользователя
let user = await userRepo.findByWalletAddress(normalized);
if (!user) {
user = await userRepo.create({ walletAddress: normalized });
}
const token = jwt.sign(
{
sub: user.id,
walletAddress: normalized,
},
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
res.json({ token, userId: user.id });
} תמיכה במספר ארנקים
// Привязка дополнительного кошелька к аккаунту
async function linkWallet(userId: string, address: string, signature: string) {
const existing = await walletRepo.findByAddress(address.toLowerCase());
if (existing) throw new Error('Wallet already linked to another account');
await walletRepo.create({ userId, address: address.toLowerCase(), linkedAt: new Date() });
} השוואת אפשרויות אחסון Nonce
| אחסון | TTL | סובלנות לתקלות | מהירות |
|---|---|---|---|
| Redis | 5 דקות | גבוהה (Redis Cluster) | < 1 ms |
| PostgreSQL | 5 דקות | בינונית (טרנזקציות) | < 10 ms |
| In-memory (Map) | אין | נמוכה (אבוד בהפעלה מחדש) | < 0.1 ms |
אנו ממליצים על Redis: TTL מובנה, פעולות אטומיות, אשכולות. עבור MVP, אחסון בזיכרון יספיק, אך לייצור, השתמשו ב-Redis.
מה כלול בעבודה שלנו
אנו מספקים:
- ביקורת אבטחה של ארכיטקטורת האימות הנוכחית שלכם
- שילוב MetaMask SDK (או ספק אחר) בפרונטאנד
- פיתוח נקודת קצה nonce עם TTL ואחסון Redis
- יישום אימות חתימה על Node.js (ethers.js)
- הפקת ואימות JWT, עם תמיכה ב-refresh token
- בדיקת כל הזרימות (התחברות מוצלחת, שגיאות, ניסיונות חוזרים)
- תיעוד API והוראות למשתמש
- אחריות תמיכה ל-30 יום לאחר השילוב
טעויות אינטגרציה נפוצות
- נורמליזציה לא נכונה של כתובת (אותיות רישיות) — כתובות Ethereum חייבות להיות באותיות קטנות לפני האימות.
- חוסר בדיקת nonce בצד השרת — החתימה עלולה להיות משוחזרת.
- אחסון nonces ללא TTL — מוביל להצטברות אינסופית והתקפות מניעת שירות.
- שימוש באותו nonce למספר בקשות — הפרת אבטחה.
כמה זמן לוקחת האינטגרציה?
יישום בסיסי (nonce + JWT) לוקח 2 עד 3 ימים. אם יש צורך בתמיכה במספר ארנקים והתחברות חלופית, צפו עד 5 ימים. צרו קשר — נעריך את הפרויקט שלכם וניתן לכם לוחות זמנים מדויקים.
ניסיון: השלמנו למעלה מ-50 אינטגרציות של ארנקי קריפטו. אנו מבטיחים אבטחת חתימות וללא דליפות nonce. הזמינו אינטגרציית MetaMask היום — המשתמשים שלכם יודו לכם. קבלו ייעוץ לפרויקט שלכם עכשיו.







