पासवर्ड को एक महँगे फ़ंक्शन से हैश करें, पूरी जानकारी के साथ सेशन और JWT के बीच चुनाव करें, और मिडलवेयर से अपने रूट की रक्षा करें।
इस पाठ को Kodokon में खोलेंपासवर्ड संग्रहीत करने का मतलब है भविष्य की किसी सेंधमारी के लिए तैयार रहना: हैशिंग को इस तरह डिज़ाइन करें कि वह डेटाबेस की चोरी से भी बची रहे। SHA-256 जैसे तेज़ हैश को GPU पर प्रति सेकंड अरबों प्रयासों की दर से ब्रूट-फ़ोर्स किया जा सकता है। आपको एक जानबूझकर महँगे फ़ंक्शन की ज़रूरत है - scrypt, जो node:crypto द्वारा दिया जाता है, या bcrypt/argon2 - और हर उपयोगकर्ता के लिए एक यादृच्छिक सॉल्ट, जो पूर्व-गणना की गई तालिकाओं को बेकार कर देता है। सॉल्ट कोई रहस्य नहीं है: इसे हैश के बगल में सादे टेक्स्ट में संग्रहीत किया जाता है।
import {
randomBytes,
scryptSync,
timingSafeEqual,
} from 'node:crypto';
export function hashPassword(password) {
const salt = randomBytes(16).toString('hex');
const hash = scryptSync(password, salt, 64)
.toString('hex');
return `${salt}:${hash}`;
}
export function verifyPassword(password, stored) {
const [salt, hash] = stored.split(':');
const candidate = scryptSync(password, salt, 64);
const expected = Buffer.from(hash, 'hex');
return timingSafeEqual(candidate, expected);
}उपयोगकर्ता को लॉग-इन बनाए रखने के दो मॉडल। सेशन: एक httpOnly कुकी में एक अपारदर्शी पहचानकर्ता, जिसकी स्थिति सर्वर की ओर होती है। तत्काल निरसन, JavaScript के लिए अदृश्य कुकी, लेकिन जैसे ही आप दूसरा इंस्टेंस जोड़ते हैं, एक साझा स्टोर (Redis) आवश्यक हो जाता है। JWT: टोकन में अंतर्निहित हस्ताक्षरित स्थिति, बिना किसी स्टोर के सत्यापन योग्य - सर्विसों के बीच आदर्श - लेकिन समाप्ति से पहले अनिरसनीय। ईमानदार समझौता: एक क्लासिक वेब एप्लिकेशन के लिए सेशन, तीसरे पक्षों द्वारा उपयोग की जाने वाली API या वितरित आर्किटेक्चर के लिए अल्पजीवी JWT।
import jwt from 'jsonwebtoken';
const SECRET = process.env.JWT_SECRET;
if (!SECRET) {
throw new Error('JWT_SECRET must be set');
}
export function signToken(user) {
return jwt.sign(
{ sub: user.id, email: user.email },
SECRET,
{ expiresIn: '15m' },
);
}सुरक्षा मिडलवेयर एक्सेस नियंत्रण को अलग निकाल देता है: यह Authorization: Bearer हेडर से टोकन निकालता है, उसे सत्यापित करता है, डिकोड की गई पहचान को req.user से जोड़ता है, या पिछले पाठ के एरर मिडलवेयर की ओर भेजे गए एक 401 के साथ बात को वहीं ख़त्म कर देता है। इसे रूट-दर-रूट के बजाय रूट के पूरे समूह की रक्षा के लिए राउटर स्तर पर (router.use(requireAuth)) लागू करें।
import jwt from 'jsonwebtoken';
import { HttpError } from './http-error.js';
const SECRET = process.env.JWT_SECRET;
export function requireAuth(req, res, next) {
const header = req.headers.authorization ?? '';
const [scheme, token] = header.split(' ');
if (scheme !== 'Bearer' || !token) {
return next(new HttpError(401, 'Missing token'));
}
try {
req.user = jwt.verify(token, SECRET);
next();
} catch {
next(new HttpError(401, 'Invalid or expired token'));
}
}timingSafeEqual किस लिए है?