हममें से अधिकांश ने कम से कम एक बार खाता पुनर्प्राप्ति प्रक्रिया का अनुभव किया है - जब हम कोई पासवर्ड भूल जाते हैं, तो एक नया पासवर्ड बनाने और सिस्टम तक पहुंच पुनः प्राप्त करने के लिए प्रक्रियाओं की आवश्यकता होती है। यह लेख मार्गों को संभालने और आवश्यक संचालन करने के लिए एक्सप्रेस के साथ-साथ Node.js, Knex और कुछ अज्ञात उपकरणों का उपयोग करके ऐसी प्रक्रिया को लागू करने पर केंद्रित है।
हम राउटर कार्यान्वयन, यूआरएल मापदंडों को संभालने, यह निर्धारित करने कि उपयोगकर्ता को क्या भेजना है जब सबूत के रूप में केवल एक ईमेल या फोन नंबर उपलब्ध हो, ईमेल सबमिशन प्रबंधित करना और सुरक्षा चिंताओं को संबोधित करना शामिल होगा।
कोडिंग में उतरने से पहले, मैं यह सुनिश्चित करना चाहूंगा कि हम उसी कोडबेस के साथ काम कर रहे हैं, जिसे आप मेरी पब्लिक से एक्सेस कर सकते हैं
अब, भूले हुए पासवर्ड प्रवाह की स्कीमा पर एक नज़र डालें।
सर्वर उपयोगकर्ता मेलबॉक्स पर ईमेल भेजने के लिए जिम्मेदार होगा जिसमें पासवर्ड रीसेट करने के लिए एक वैध लिंक होगा, और टोकन और उपयोगकर्ता अस्तित्व को भी मान्य करेगा।
ईमेल सेवा का उपयोग शुरू करने और Node.js के साथ ईमेल भेजने के लिए, हमें अपनी मौजूदा निर्भरताओं के अलावा निम्नलिखित पैकेज स्थापित करने की आवश्यकता है:
npm i --save nodemailer handlebars
नोडमेलर : शक्तिशाली मॉड्यूल जो एसएमटीपी या अन्य परिवहन तंत्र का उपयोग करके आसानी से ईमेल भेजने की अनुमति देता है।
हैंडलबार्स : हैंडलबार्स जावास्क्रिप्ट के लिए एक लोकप्रिय टेम्प्लेटिंग इंजन है। यह हमें प्लेसहोल्डर्स के साथ टेम्प्लेट परिभाषित करने की अनुमति देगा जिन्हें रेंडर करते समय डेटा से भरा जा सकता है।
अब, हमें माइग्रेशन बनाने की आवश्यकता है, इसलिए मेरे मामले में, मुझे users
तालिका में एक नया कॉलम forgot_password_token
जोड़ना होगा:
knex migrate:make add_field_forgot_password_token -x ts
और जेनरेट की गई फ़ाइल में, मैंने कोड सेट किया है:
import type { Knex } from 'knex'; export async function up(knex: Knex): Promise<void> { return knex.schema.alterTable('users', table => { table.string('forgot_password_token').unique(); }); } export async function down(knex: Knex): Promise<void> { return knex.schema.alterTable('users', table => { table.dropColumn('forgot_password_token'); }); }
उपयोगकर्ता तालिका में पासवर्ड भूल गए टोकन के लिए स्थानांतरण
और फिर नवीनतम फ़ाइल माइग्रेट करें:
knex migrate:knex
तो अब हम users
तालिका में अपना forgot_password_token
सेट कर सकते हैं
पासवर्ड भूलने और रीसेट करने के तर्क को संभालने के लिए जिम्मेदार नियंत्रकों को प्रबंधित करने के लिए, हमें दो मार्ग स्थापित करने होंगे। पहला रूट पासवर्ड भूलने की प्रक्रिया शुरू करता है, जबकि दूसरा रीसेट प्रक्रिया को संभालता है, सत्यापन के लिए यूआरएल में एक टोकन पैरामीटर की अपेक्षा करता है। इसे कार्यान्वित करने के लिए, src/routes/
निर्देशिका के भीतर एक फ़ाइल बनाएं जिसका नाम forgotPasswordRouter.ts
है, और निम्नलिखित कोड डालें:
import { Router } from 'express'; import { forgotPasswordController } from 'src/controllers/forgotPasswordController'; import { resetPasswordController } from 'src/controllers/resetPasswordController'; export const forgotPasswordRouter = Router(); forgotPasswordRouter.post('/', forgotPasswordController); forgotPasswordRouter.post('/reset/:token', resetPasswordController);
पासवर्ड भूल गए राउटर
दो नियंत्रक ईमेल भेजने और पासवर्ड रीसेट करने के लिए तर्क का प्रबंधन करेंगे।
जब ग्राहक अपना पासवर्ड भूल जाता है तो उसके पास कोई सत्र नहीं होता है, जिसका अर्थ है कि हम ईमेल या किसी अन्य सुरक्षा पहचानकर्ता को छोड़कर उपयोगकर्ता डेटा प्राप्त नहीं कर सकते हैं। हमारे मामले में, हम पासवर्ड रीसेट को संभालने के लिए एक ईमेल भेज रहे हैं। वह तर्क हम नियंत्रक में सेट करने जा रहे हैं।
forgotPasswordRouter.post('/', forgotPasswordController);
'पासवर्ड भूल गए?' याद है? लॉगिन फॉर्म के नीचे लिंक आमतौर पर लॉगिन फॉर्म में किसी भी क्लाइंट के यूआई में होता है? इस पर क्लिक करने से हमें एक दृश्य मिलता है जहां हम पासवर्ड रीसेट का अनुरोध कर सकते हैं। हम बस अपना ईमेल इनपुट करते हैं, और नियंत्रक सभी आवश्यक प्रक्रियाओं को संभालता है। आइए निम्नलिखित कोड की जाँच करें:
import { Request, Response } from 'express'; import { UserModel } from 'src/models/UserModel'; import type { User } from 'src/@types'; import { TokenService } from 'src/services/TokenService'; import { EmailService } from 'src/services/EmailService'; export const forgotPasswordController = async (req: Request, res: Response) => { try { const { email, }: { email: string; } = req.body; const user = await UserModel.findByEmail(email); if (user) { const token = await TokenService.sign( { id: user.id, }, { expiresIn: '1 day', } ); await user.context.update({ forgot_password_token: token }); await EmailService.sendPasswordResetEmail(email, token); } return res.sendStatus(200); } catch (error) { return res.sendStatus(500); } };
पासवर्ड नियंत्रक भूल गए
मुख्य भाग से, हमें एक ईमेल प्राप्त होगा, और फिर हम UserModel.findByEmail
उपयोग करके उपयोगकर्ता को ढूंढेंगे। यदि उपयोगकर्ता मौजूद है, तो हम TokenService.sign
उपयोग करके एक जेडब्ल्यूटी टोकन बनाते हैं और 1 दिन की समाप्ति के साथ टोकन को उपयोगकर्ता forgot_password_token
में सहेजते हैं। फिर हम एक उचित लिंक के साथ एक टोकन के साथ ईमेल पर संदेश भेजेंगे जहां उपयोगकर्ता अपना पासवर्ड बदल सकेगा।
ईमेल भेजने में सक्षम होने के लिए, हमें अपना नया ईमेल पता बनाना होगा जो एक प्रेषक होगा।
आइए एक नया ईमेल खाता बनाने के लिए Google पर जाएँ, और फिर, जब खाता बन जाए, तो अपना Google खाता प्रबंधित करें लिंक पर आगे बढ़ें। आप इसे ऊपर दाईं ओर अवतार पर क्लिक करके पा सकते हैं। फिर, बाएं मेनू पर, सुरक्षा आइटम पर क्लिक करें और फिर 2-चरणीय सत्यापन दबाएँ। नीचे आपको ऐप पासवर्ड अनुभाग मिलेगा, तीर पर क्लिक करें:
वह नाम दर्ज करें जिसका उपयोग करना आवश्यक है। मेरे मामले में, मैं Nodemailer
सेट करता हूं और Create दबाता हूं।
जनरेट किया गया पासवर्ड कॉपी करें, और इसे अपनी .env
फ़ाइल पर सेट करें। हमें दो वेरिएबल फ़ाइल करने के लिए सेट करने की आवश्यकता है:
MAIL_USER="[email protected]" MAIL_PASSWORD="vyew hzek avty iwst"
बेशक, info@company_name.com
जैसा उचित ईमेल पाने के लिए, आपको AWS SES, या किसी अन्य सेवाओं के साथ Google Workspace या AWS Amazon WorkMail सेट करना होगा। लेकिन हमारे मामले में, हम एक साधारण जीमेल खाते का निःशुल्क उपयोग कर रहे हैं।
.env
फ़ाइल तैयार होने के साथ, हम ईमेल भेजने के लिए अपनी सेवा स्थापित करने के लिए तैयार हैं। नियंत्रक हमारे संदेश के लिए उत्पन्न टोकन और प्राप्तकर्ता ईमेल पते के साथ सेवा का उपयोग करेगा।
await EmailService.sendPasswordResetEmail(email, token);
आइए src/services/EmailService.ts
बनाएं और सेवा के लिए वर्ग को परिभाषित करें:
export class EmailService {}
और अब प्रारंभिक डेटा के रूप में, मुझे nodemailer
के साथ उपयोग करने के लिए पर्यावरण प्राप्त करना होगा:
import process from 'process'; import * as nodemailer from 'nodemailer'; import * as dotenv from 'dotenv'; dotenv.config(); export class EmailService { private static transporter: nodemailer.Transporter; private static env = { USER: process.env.MAIL_USER, PASS: process.env.MAIL_PASSWORD, }; }
ईमेल सेवा
हमें सर्विस इनिशियलाइज़ेशन का ध्यान रखना होगा। मैंने इसके बारे में पहले भी अपने पिछले लेख में लिखा था
import { TokenService } from 'src/services/TokenService'; import { RedisService } from 'src/services/RedisService'; import { EmailService } from 'src/services/EmailService'; export const initialize = async () => { await RedisService.initialize(); TokenService.initialize(); EmailService.initialize(); };
सेवाएँ प्रारंभ करना
अब, आइए अपने EmailService
वर्ग के भीतर आरंभीकरण बनाने के लिए आगे बढ़ें:
import process from 'process'; import * as nodemailer from 'nodemailer'; import * as dotenv from 'dotenv'; dotenv.config(); export class EmailService { private static transporter: nodemailer.Transporter; private static env = { USER: process.env.MAIL_USER, PASS: process.env.MAIL_PASSWORD, }; public static initialize() { try { EmailService.transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: this.env.USER, pass: this.env.PASS, }, }); } catch (error) { console.error('Error initializing email service'); throw error; } } }
ईमेल सेवा आरंभीकरण
इनिशियलाइज़ेशन nodemailer.createTransport()
है, जो nodemailer
लाइब्रेरी द्वारा प्रदान की गई एक विधि है। यह एक ट्रांसपोर्टर ऑब्जेक्ट बनाता है जिसका उपयोग हमारे ईमेल भेजने के लिए किया जाएगा। विधि एक विकल्प ऑब्जेक्ट को एक तर्क के रूप में स्वीकार करती है जहां आप ट्रांसपोर्टर के लिए कॉन्फ़िगरेशन विवरण निर्दिष्ट करते हैं।
हम Google: service: 'gmail'
ईमेल सेवा प्रदाता को निर्दिष्ट करता है। नोडमेलर विभिन्न ईमेल सेवा प्रदाताओं के लिए अंतर्निहित समर्थन प्रदान करता है, और gmail
इंगित करता है कि ट्रांसपोर्टर को जीमेल के एसएमटीपी सर्वर के साथ काम करने के लिए कॉन्फ़िगर किया जाएगा।
प्रमाणीकरण auth
के लिए, ईमेल सेवा प्रदाता के एसएमटीपी सर्वर तक पहुंचने के लिए आवश्यक क्रेडेंशियल सेट करना आवश्यक है।
user
के लिए वह ईमेल पता सेट किया जाना चाहिए जिससे हम ईमेल भेजने जा रहे हैं, और वह पासवर्ड ऐप पासवर्ड से Google खाते में जेनरेट किया गया है।
अब, आइए अपनी सेवा का अंतिम भाग सेट करें:
import process from 'process'; import * as nodemailer from 'nodemailer'; import * as dotenv from 'dotenv'; import { generateAttachments } from 'src/helpers/generateAttachments'; import { generateTemplate } from 'src/helpers/generateTemplate'; import { getHost } from 'src/helpers/getHost'; dotenv.config(); export class EmailService { // ...rest code public static async sendPasswordResetEmail(email: string, token: string) { try { const host = getHost(); const template = generateTemplate<{ token: string; host: string; }>('passwordResetTemplate', { token, host }); const attachments = generateAttachments([{ name: 'email_logo' }]); const info = await EmailService.transporter.sendMail({ from: this.env.USER, to: email, subject: 'Password Reset', html: template, attachments, }); console.log('Message sent: %s', info.messageId); } catch (error) { console.error('Error sending email: ', error); } } }
पासवर्ड रीसेट ईमेल भेजें
आगे बढ़ने से पहले, क्लाइंट को ईमेल प्राप्त होने पर उपयुक्त होस्ट का निर्धारण करना महत्वपूर्ण है। ईमेल के मुख्य भाग में टोकन के साथ एक लिंक स्थापित करना आवश्यक है।
import * as dotenv from 'dotenv'; import process from 'process'; dotenv.config(); export const getHost = (): string => { const isProduction = process.env.NODE_ENV === 'production'; const protocol = isProduction ? 'https' : 'http'; const port = isProduction ? '' : `:${process.env.CLIENT_PORT}`; return `${protocol}://${process.env.WEB_HOST}${port}`; };
मेज़बान प्राप्त करें
टेम्प्लेट के लिए, मैं handlebars
उपयोग कर रहा हूं और इसके लिए, हमें src/temlates/passwordResetTemplate.hbs
में अपना पहला HTML टेम्प्लेट बनाना होगा:
<!-- passwordResetTemplate.hbs --> <html lang='en'> <head> <style> a { color: #372aff; } .token { font-weight: bold; } </style> <title>Forgot Password</title> </head> <body> <p>You requested a password reset. Please use the following link to reset your password:</p> <a class='token' href="{{ host }}/reset-password/{{ token }}">Reset Password</a> <p>If you did not request a password reset, please ignore this email.</p> <img src="cid:email_logo" alt="Email Logo"/> </body> </html>
पासवर्ड रीसेट टेम्पलेट
और अब हम सहायक के साथ इस टेम्पलेट का पुन: उपयोग कर सकते हैं:
import path from 'path'; import fs from 'fs'; import handlebars from 'handlebars'; export const generateTemplate = <T>(name: string, props: T): string => { const templatePath = path.join(__dirname, '..', 'src/templates', `${name}.hbs`); const templateSource = fs.readFileSync(templatePath, 'utf8'); const template = handlebars.compile(templateSource); return template(props); };
टेम्प्लेट हेल्पर जनरेट करें
अपने ईमेल को बेहतर बनाने के लिए हम अनुलग्नक भी शामिल कर सकते हैं। ऐसा करने के लिए, email_logo.png
फ़ाइल को src/assets
फ़ोल्डर में जोड़ें। फिर हम निम्नलिखित सहायक फ़ंक्शन का उपयोग करके इस छवि को ईमेल के भीतर प्रस्तुत कर सकते हैं:
import path from 'path'; import { Extension } from 'src/@types/enums'; type AttachmentFile = { name: string; ext?: Extension; cid?: string; }; export const generateAttachments = (files: AttachmentFile[] = []) => files.map(file => { const ext = file.ext || Extension.png; const filename = `${file.name}.${ext}`; const imagePath = path.join(__dirname, '..', 'src/assets', filename); return { filename, path: imagePath, cid: file.cid || file.name, }; });
अनुलग्नक सहायक उत्पन्न करें
उन सभी सहायकों को एकत्रित करने के बाद, हमें इसका उपयोग करके ईमेल भेजने में सक्षम होना होगा:
const info = await EmailService.transporter.sendMail({ from: this.env.USER, to: email, subject: 'Password Reset', html: template, attachments, });
यह दृष्टिकोण सभ्य मापनीयता प्रदान करता है, जिससे सेवा विविध सामग्री के साथ ईमेल भेजने के लिए विभिन्न तरीकों को नियोजित करने में सक्षम हो जाती है।
अब, आइए अपने राउटर के साथ नियंत्रक को ट्रिगर करने का प्रयास करें और ईमेल भेजें। उसके लिए, मैं उपयोग कर रहा हूँ
कंसोल आपको बताएगा कि संदेश भेज दिया गया है:
Message sent: <1k96ah55-c09t-p9k2–[email protected]>
इनबॉक्स में नए संदेशों की जाँच करें:
पासवर्ड रीसेट करने के लिंक में टोकन और होस्ट शामिल होना चाहिए:
http://localhost:3000/reset-password/<token>
पोर्ट 3000
यहाँ निर्दिष्ट है क्योंकि यह संदेश विकास प्रक्रिया से संबंधित है। यह इंगित करता है कि पासवर्ड रीसेट के लिए प्रपत्रों को संभालने के लिए जिम्मेदार क्लाइंट भी विकास परिवेश में काम कर रहा होगा।
टोकन को नियंत्रक पक्ष पर टोकनसर्विस के साथ सत्यापित करना होगा जहां से हम उस उपयोगकर्ता को प्राप्त कर सकते हैं जिसने वह ईमेल भेजा है। आइए उस राउटर को पुनर्प्राप्त करें जो टोकन का उपयोग करता है:
forgotPasswordRouter.post('/reset/:token', resetPasswordController);
नियंत्रक केवल तभी पासवर्ड अपडेट करेगा जब टोकन वैध है और समाप्त नहीं हुआ है, समाप्ति समय एक घंटे के लिए निर्धारित है। इस कार्यक्षमता को कार्यान्वित करने के लिए, src/controllers/
फ़ोल्डर पर नेविगेट करें और निम्नलिखित कोड वाली resetPasswordController.ts
नामक एक फ़ाइल बनाएं:
import bcrypt from 'bcrypt'; import { Request, Response } from 'express'; import { TokenService } from 'src/services/TokenService'; import { UserModel } from 'src/models/UserModel'; import type { User } from 'src/@types'; export const resetPasswordController = async (req: Request, res: Response) => { try { const token = req.params.token; if (!token) { return res.sendStatus(400); } const userData = await TokenService.verify<{ id: number }>(token); const user = await UserModel.findOneById<User>(userData.id); if (!user) { return res.sendStatus(400); } const newPassword = req.body.password; if (!newPassword) { return res.sendStatus(400); } const hashedPassword = await bcrypt.hash(newPassword, 10); await UserModel.updateById(user.id, { password: hashedPassword, passwordResetToken: null }); return res.sendStatus(200); } catch (error) { const errors = ['jwt malformed', 'TokenExpiredError', 'invalid token']; if (errors.includes(error.message)) { return res.sendStatus(400); } return res.sendStatus(500); } };
पासवर्ड नियंत्रक रीसेट करें
यह नियंत्रक टोकन प्राप्त करेगा, इसे सत्यापित करेगा, डिक्रिप्ट किए गए डेटा से उपयोगकर्ता आईडी निकालेगा, संबंधित उपयोगकर्ता को पुनः प्राप्त करेगा, अनुरोध निकाय में क्लाइंट द्वारा भेजा गया नया पासवर्ड प्राप्त करेगा, और डेटाबेस में पासवर्ड को अपडेट करने के लिए आगे बढ़ेगा। अंततः, यह क्लाइंट को नए पासवर्ड का उपयोग करके लॉग इन करने में सक्षम बनाता है।
ईमेल सेवा की स्केलेबिलिटी विभिन्न दृष्टिकोणों के माध्यम से प्रदर्शित की जाती है, जैसे पुष्टिकरण या सफलता संदेश भेजना, जैसे पासवर्ड अपडेट का संकेत देना और बाद में लॉगिन को सक्षम करना। हालाँकि, पासवर्ड प्रबंधित करना एक बड़ी चुनौती है, खासकर जब एप्लिकेशन सुरक्षा बढ़ाना अनिवार्य हो।
सुरक्षा को मजबूत करने के लिए कई विकल्प उपलब्ध हैं, जिनमें पासवर्ड परिवर्तन की अनुमति देने से पहले अतिरिक्त जांच, जैसे टोकन तुलना, ईमेल और पासवर्ड सत्यापन शामिल हैं।
एक अन्य विकल्प पिन कोड प्रणाली लागू करना है, जहां सर्वर साइड पर सत्यापन के लिए उपयोगकर्ता के ईमेल पर एक कोड भेजा जाता है। इनमें से प्रत्येक उपाय के लिए ईमेल भेजने की क्षमताओं के उपयोग की आवश्यकता होती है।
सभी कार्यान्वित कोड आप यहां पा सकते हैं
कृपया बेझिझक इस निर्माण के साथ कोई भी प्रयोग करें और इस विषय के किन पहलुओं की आप सराहना करते हैं, इस पर अपनी प्रतिक्रिया साझा करें। आपका बहुत-बहुत धन्यवाद।
यहां, आप कई संदर्भ पा सकते हैं जिनका उपयोग मैंने इस लेख में किया है:
यहाँ भी प्रकाशित किया गया