परिचय
यह एक निर्विवाद वास्तविकता है कि यदि आप उपयोगकर्ता डेटा को सुरक्षित करना चाहते हैं और जानकारी तक सुरक्षित पहुंच को सक्षम करना चाहते हैं तो प्रमाणीकरण किसी भी एप्लिकेशन या सिस्टम में महत्वपूर्ण है। प्रमाणीकरण यह स्थापित करने या प्रदर्शित करने की प्रक्रिया है कि कुछ सत्य, वैध या मान्य है।
आवश्यकताएं
यह ट्यूटोरियल एक व्यावहारिक प्रदर्शन है। साथ चलने के लिए, सुनिश्चित करें कि आपके पास निम्नलिखित स्थान हैं:
- आपके सिस्टम में Node.js चल रहे हैं क्योंकि NestJS एक Node.js फ्रेमवर्क है
- मोंगोडीबी स्थापित
NestJS क्या है?
Nest (NestJS) स्केलेबल, कुशल अनुप्रयोगों के निर्माण के लिए एक Node.js सर्वर-साइड एप्लिकेशन फ्रेमवर्क है।
यह टाइपस्क्रिप्ट में लिखा गया है और एक्सप्रेस पर बनाया गया है, एक बहुत ही न्यूनतर ढांचा जो अपने आप में बहुत अच्छा है लेकिन इसमें संरचना का अभाव है। यह ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग, फंक्शनल प्रोग्रामिंग और फंक्शनल रिएक्टिव प्रोग्रामिंग जैसे प्रोग्रामिंग प्रतिमानों को जोड़ती है।
यदि आप अपने बैकएंड पर बहुत अधिक संरचना चाहते हैं तो यह उपयोग करने के लिए एक ढांचा है। इसका सिंटैक्स और संरचना एंगुलरजेएस के समान है, जो एक फ्रंट-एंड फ्रेमवर्क है। और यह उसी तरह टाइपस्क्रिप्ट, सेवाओं और निर्भरता इंजेक्शन का उपयोग करता है जैसे AngularJS करता है।
यह मॉड्यूल और नियंत्रकों को नियोजित करता है, और आप कमांड-लाइन इंटरफ़ेस का उपयोग करके फ़ाइल के लिए नियंत्रक बना सकते हैं।
NestJS मॉड्यूल आपको संबंधित नियंत्रकों और सेवा प्रदाताओं को एक ही कोड फ़ाइल में समूहित करने की अनुमति देता है। सीधे शब्दों में कहें, NestJS मॉड्यूल एक टाइपस्क्रिप्ट फ़ाइल है जिसमें @Module . होता है एनोटेशन ()। यह डेकोरेटर नेस्टजेएस ढांचे को सूचित करता है कि कौन से नियंत्रक, सेवा प्रदाता, और अन्य संबद्ध संसाधनों को तत्काल और बाद में ऐप कोड द्वारा उपयोग किया जाएगा।
सत्र-आधारित प्रमाणीकरण क्या है?
सत्र-आधारित प्रमाणीकरण उपयोगकर्ता प्रमाणीकरण की एक विधि है जिसमें सर्वर एक सफल लॉग-इन के बाद एक सत्र बनाता है, जिसमें सत्र आईडी आपके ब्राउज़र में कुकी या स्थानीय संग्रहण में संग्रहीत होती है।
बाद के अनुरोधों पर, आपकी कुकी को सर्वर पर संग्रहीत सत्र आईडी के विरुद्ध मान्य किया जाता है। यदि कोई मेल है, तो अनुरोध को मान्य और संसाधित माना जाता है।
इस प्रमाणीकरण पद्धति का उपयोग करते समय, निम्नलिखित सुरक्षा सर्वोत्तम प्रथाओं को ध्यान में रखना महत्वपूर्ण है:
- ब्रूट फ़ोर्स अटैक को अप्रभावी बनाने के लिए लंबी और रैंडम सेशन आईडी (128 बिट अनुशंसित लंबाई है) जेनरेट करें
- किसी भी संवेदनशील या उपयोगकर्ता-विशिष्ट डेटा को संग्रहीत करने से बचें
- सभी सत्र-आधारित ऐप्स के लिए HTTPS संचार अनिवार्य करें
- ऐसी कुकी बनाएं जिनमें सुरक्षित और केवल HTTP विशेषताएं हों
सत्र-आधारित प्रमाणीकरण क्यों?
सत्र-आधारित प्रमाणीकरण अधिकांश प्रमाणीकरण विधियों की तुलना में अधिक सुरक्षित है क्योंकि यह सरल, सुरक्षित और सीमित भंडारण आकार है। इसे समान रूट डोमेन में वेबसाइटों के लिए सबसे अच्छा विकल्प भी माना जाता है।
प्रोजेक्ट सेटअप
दुनिया भर में Nest CLI इंस्टॉल करके अपना प्रोजेक्ट सेटअप शुरू करें। अगर आपके पास पहले से NestJS CLI इंस्टॉल है, तो आपको ऐसा करने की ज़रूरत नहीं है।
Nest CLI, Nest ऐप्लिकेशन को सेट अप करने, विकसित करने और बनाए रखने के लिए एक कमांड-लाइन इंटरफ़ेस टूल है।
npm i -g @nestjs/cli
अब, निम्न कमांड चलाकर अपना प्रोजेक्ट सेट करें:
nest new session-based-auth
उपरोक्त कमांड कुछ बॉयलरप्लेट्स के साथ एक नेस्ट एप्लिकेशन बनाता है, फिर आपको अपना एप्लिकेशन चलाने के लिए आवश्यक मॉड्यूल स्थापित करने के लिए अपना पसंदीदा पैकेज मैनेजर चुनने के लिए प्रेरित करता है। प्रदर्शन के लिए, यह ट्यूटोरियल npm . का उपयोग करता है . npm . के साथ जारी रखने के लिए एंटर कुंजी दबाएं ।
यदि सब कुछ ठीक रहा, तो आपको अपने टर्मिनल पर नीचे स्क्रीनशॉट में जैसा आउटपुट दिखाई देगा।
एक बार इंस्टॉलेशन पूरा हो जाने के बाद, अपनी प्रोजेक्ट डायरेक्टरी में जाएँ, और नीचे दिए गए कमांड के साथ एप्लिकेशन चलाएँ:
npm run start:dev
उपरोक्त आदेश एप्लिकेशन चलाता है और परिवर्तनों के लिए देखता है। आपका प्रोजेक्ट src
फ़ोल्डर संरचना इस प्रकार दिखनी चाहिए।
└───src
│ └───app.controller.ts
│ └───app.modules.ts
│ └───app.service.ts
│ └───main.ts
निर्भरताएं स्थापित करें
अब जब आपका एप्लिकेशन सेट हो गया है, तो आइए आवश्यक निर्भरताएं स्थापित करें।
npm install --save @nestjs/passport passport passport-local
उपरोक्त आदेश Passport.js, एक लोकप्रिय Nest.js प्रमाणीकरण लाइब्रेरी स्थापित करता है।
साथ ही, नीचे दिए गए आदेश के साथ रणनीति के प्रकार स्थापित करें:
इसमें passport-local
. के लिए टाइप परिभाषाएं शामिल हैं ।
npm install --save-dev @types/passport-local
NestJS में MongoDB डेटाबेस सेट करें
अपना डेटाबेस सेट अप और कनेक्ट करने के लिए, निम्न आदेश के साथ नेवला पैकेज और NestJS आवरण स्थापित करें:
npm install --save @nestjs/mongoose mongoose
Mongoose NestJS रैपर आपको NestJS एप्लिकेशन में Mongoose का उपयोग करने में मदद करता है और स्वीकृत टाइपस्क्रिप्ट समर्थन देता है।
अब, अपने app.module.ts
. पर जाएं , और आयात करें mongoose
@nestjs/mongoose
. से मॉड्यूल . फिर forRoot()
. पर कॉल करें विधि, नेवला मॉड्यूल द्वारा प्रदान की गई एक विधि, और अपने डेटाबेस URL स्ट्रिंग में पास करें।
app.module.ts
. में अपना डेटाबेस कनेक्शन सेट करना सर्वर के शुरू होते ही आपके एप्लिकेशन को तुरंत डेटाबेस से कनेक्ट करने में मदद करता है - आपके एप्लिकेशन को चलाने के बाद क्योंकि यह लोड होने वाला पहला मॉड्यूल है।
app.module.ts
import { Module } from "@nestjs/common"
import { MongooseModule } from "@nestjs/mongoose"
import { AppController } from "./app.controller"
import { AppService } from "./app.service"
@Module({
imports: [
MongooseModule.forRoot(
"mongodb+srv://<username>:<password>@cluster0.kngtf.mongodb.net/session-auth?retryWrites=true&w=majority"
),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
उपयोगकर्ता मॉड्यूल बनाएं
पृथक्करण संबंधी चिंताओं के लिए, अपने कोड को साफ और सुव्यवस्थित बनाने के लिए, विशेष रूप से निम्नलिखित कमांड चलाकर NestJS CLI का उपयोग करने वाले उपयोगकर्ताओं के लिए एक मॉड्यूल बनाएं:
nest g module users
उपरोक्त आदेश एक users
. बनाता है users.module.ts
. के साथ फ़ोल्डर और अपडेट करता है app.module.ts
साथ ही, users.service.ts
create बनाएं और users.controller.ts
निम्नलिखित कमांड वाली फाइलें:
nest g service users
nest g controller users
ध्यान दें कि आप नेस्ट सीएलआई का उपयोग किए बिना मैन्युअल रूप से अपने फ़ोल्डर्स और फाइलें बना सकते हैं, लेकिन सीएलआई का उपयोग करने से आवश्यक फ़ोल्डर्स स्वतः अपडेट हो जाते हैं और आपका जीवन आसान हो जाता है।
उपयोगकर्ता स्कीमा बनाएं
अगला चरण अपनी UserSchema बनाना है, लेकिन पहले, एक users.model.ts
जोड़ें फ़ाइल, जहाँ आप UserSchema
बनाएंगे
यह हमारे आवेदन का आकार होना चाहिए src
अब फ़ोल्डर।
└───src
│ └───users
│ │ └───users.controller.ts
│ │ └───users.model.ts
│ │ └───users.module.ts
│ │ └───users.service.ts
│ └───app.controller.ts
│ └───app.module.ts
│ └───app.service.ts
│ └───main.ts
UserSchema
create बनाने के लिए , नेवला के रूप में सब कुछ आयात करें users.model.ts
में नेवला पैकेज से . फिर नए नेवला स्कीमा को कॉल करें, उपयोगकर्ता मॉडल का एक खाका, और एक JavaScript ऑब्जेक्ट में पास करें जहां आप उपयोगकर्ता ऑब्जेक्ट और डेटा को परिभाषित करेंगे।
users.model.ts
import * as mongoose from "mongoose"
export const UserSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
)
export interface User extends mongoose.Document {
_id: string;
username: string;
password: string;
}
साथ ही, अपने मॉडल के लिए एक इंटरफ़ेस बनाएं जो नेवला का विस्तार करे, एक ऐसा दस्तावेज़ जो आपके MongoDB संग्रह को पॉप्युलेट करने में आपकी सहायता करता है।
अपने users.module.ts
पर जाएं और आयात करें MongooseModule
आयात सरणी में। फिर forFeature()
. पर कॉल करें MongooseModule
. द्वारा प्रदान की गई विधि , और ऑब्जेक्ट की एक सरणी में पास करें जो नाम और स्कीमा लेता है।
यह आपको डिपेंडेंसी इंजेक्शन की मदद से फ़ाइल को कहीं भी साझा करने में सक्षम करेगा।
users.module.ts
import { Module } from "@nestjs/common"
import { MongooseModule } from "@nestjs/mongoose"
import { UsersController } from "./users.controller"
import { UserSchema } from "./users.model"
import { UsersService } from "./users.service"
@Module({
imports: [MongooseModule.forFeature([{ name: "user", schema: UserSchema }])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
users.module.ts
. में , निर्यात करें UsersService
आपको इसे किसी अन्य मॉड्यूल में एक्सेस करने में सक्षम बनाने के लिए।
users.module.ts
import { Module } from "@nestjs/common"
import { MongooseModule } from "@nestjs/mongoose"
import { UsersController } from "./users.controller"
import { UserSchema } from "./users.model"
import { UsersService } from "./users.service"
@Module({
imports: [MongooseModule.forFeature([{ name: "user", schema: UserSchema }])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
व्यावसायिक तर्क को एक अलग वर्ग में समाहित करना आमतौर पर एक अच्छा विचार है। ऐसे वर्ग को सेवा के रूप में जाना जाता है। इस वर्ग का काम नियंत्रक के अनुरोधों को संसाधित करना और व्यावसायिक तर्क करना है।
users.service.ts
. में फ़ाइल, आयात करें Model
mongoose
. से , User
users.model.ts
. से , और InjectModel
@nestjs/mongoose
. से . फिर UsersService
. में एक विधि जोड़ें वर्ग जो एक उपयोगकर्ता नाम और पासवर्ड लेता है, और विधि को कॉल करता है insertUser()
।
users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './users.model';
@Injectable()
export class UsersService {
constructor(@InjectModel('user') private readonly userModel: Model<User>) {}
async insertUser(userName: string, password: string) {
const username = userName.toLowerCase();
const newUser = new this.userModel({
username,
password,
});
await newUser.save();
return newUser;
}
}
अब जबकि UsersService
कक्षा तैयार है, आपको इसे अपने नियंत्रक में इंजेक्ट करने की आवश्यकता है। लेकिन पहले, उपयोगकर्ताओं के पासवर्ड को सुरक्षित रूप से संग्रहीत करने के बारे में बात करते हैं।
पंजीकरण प्रक्रिया का सबसे महत्वपूर्ण पहलू उपयोगकर्ता के पासवर्ड हैं, जिन्हें सादे पाठ में सहेजा नहीं जाना चाहिए। एक मजबूत पासवर्ड बनाना उपयोगकर्ता की जिम्मेदारी है, लेकिन एक डेवलपर के रूप में यह आपका दायित्व है कि आप अपने पासवर्ड को सुरक्षित रखें। यदि कोई डेटाबेस उल्लंघन होता है, तो उपयोगकर्ताओं के पासवर्ड उजागर हो जाएंगे। और क्या होता है यदि इसे सादे पाठ में संग्रहीत किया जाता है? मुझे विश्वास है कि आप उत्तर जानते हैं। इसे संबोधित करने के लिए, पासवर्ड को bcrypt का उपयोग करके हैश करें।
तो, स्थापित करें bcrypt
और @types/bcrypt
निम्न आदेश के साथ:
npm install @types/bcrypt bcrypt
उस रास्ते से बाहर, अपना नियंत्रक सेट करें। सबसे पहले, अपनी UsersService
आयात करें क्लास और सब कुछ bcrypt
. से . फिर एक कंस्ट्रक्टर और एक विधि जोड़ें जो आपको एक उपयोगकर्ता जोड़ने की अनुमति देता है; यह आने वाले पोस्ट अनुरोधों को संभालेगा, इसे addUser
call कॉल करें , एक फ़ंक्शन बॉडी के साथ जहां आपके पास पासवर्ड हैश होगा।
users.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { UsersService } from './users.service';
import * as bcrypt from 'bcrypt';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//post / signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
}
पंजीकरण app.module.ts
. में होता है फ़ाइल, जो UsersModule
. को जोड़कर हासिल की जाती है @Module()
. पर app.module.ts
. में डेकोरेटर का आयात सरणी ।
app.module.ts
import { Module } from "@nestjs/common"
import { MongooseModule } from "@nestjs/mongoose"
import { AppController } from "./app.controller"
import { AppService } from "./app.service"
import { UsersModule } from "./users/users.module"
@Module({
imports: [
MongooseModule.forRoot(
"mongodb+srv://<username>:<password>@cluster0.kngtf.mongodb.net/session-auth?retryWrites=true&w=majority"
),
UsersModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
बधाई हो! आप पंजीकरण के साथ कर रहे हैं। अब आप उपयोगकर्ता नाम और पासवर्ड के साथ उपयोगकर्ता को पंजीकृत कर सकते हैं।
अब, पंजीकरण समाप्त होने के बाद, एक getUser
जोड़ें आपके UsersService
. पर काम करता है findOne
. के साथ उपयोगकर्ता नाम द्वारा उपयोगकर्ता को खोजने की विधि।
users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './users.model';
@Injectable()
export class UsersService {
constructor(@InjectModel('user') private readonly userModel: Model<User>) {}
async insertUser(userName: string, password: string) {
const username = userName.toLowerCase();
const newUser = new this.userModel({
username,
password,
});
await newUser.save();
return newUser;
}
async getUser(userName: string) {
const username = userName.toLowerCase();
const user = await this.userModel.findOne({ username });
return user;
}
}
प्रमाणीकरण मॉड्यूल बनाएं
जैसे ही उपयोगकर्ताओं के लिए, विशेष रूप से सभी प्रमाणीकरण/सत्यापन के लिए एक प्रमाणन मॉड्यूल और सेवा बनाएं। ऐसा करने के लिए, निम्न आदेश चलाएँ:
nest g module auth
nest g service auth
उपरोक्त एक प्रामाणिक फ़ोल्डर बनाएगा, auth.module.ts
, और auth.service.ts
, और अपडेट करें auth.module.ts
और app.module.ts
फ़ाइलें.
इस बिंदु पर, आपके आवेदन का आकार src
फ़ोल्डर इस प्रकार दिखना चाहिए।
└───src
│ └───auth
│ │ └───auth.module.ts
│ │ └───auth.service.ts
│ └───users
│ │ └───users.controller.ts
│ │ └───users.model.ts
│ │ └───users.module.ts
│ │ └───users.service.ts
│ └───app.controller.ts
│ └───app.module.ts
│ └───app.service.ts
│ └───main.ts
उपरोक्त जनरेट कमांड आपके app.module.ts
. को अपडेट करेगा , और यह नीचे दिए गए कोड स्निपेट जैसा दिखेगा:
app.module.ts
import { Module } from "@nestjs/common"
import { MongooseModule } from "@nestjs/mongoose"
import { AppController } from "./app.controller"
import { AppService } from "./app.service"
import { UsersModule } from "./users/users.module"
import { AuthModule } from './auth/auth.module';
@Module({
imports: [UsersModule, AuthModule, MongooseModule.forRoot(
//database url string
'mongodb://localhost:27017/myapp'
)],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
उपयोगकर्ताओं को प्रमाणित करें
अपने auth.module.ts
. पर जाएं फ़ाइल और जोड़ें UsersModule
UsersService
. तक पहुंच को सक्षम करने के लिए आयात सरणी में users.module.ts
. से निर्यात किया गया फ़ाइल।
auth.module.ts
import { Module } from "@nestjs/common"
import { UsersModule } from "src/users/users.module"
import { AuthService } from "./auth.service"
@Module({
imports: [UsersModule],
providers: [AuthService],
})
export class AuthModule {}
आपके auth.service.ts
. में फ़ाइल, कंस्ट्रक्टर को कॉल करें ताकि आप UsersService
इंजेक्ट कर सकें , और सत्यापन के लिए एक विधि जोड़ें जो एक उपयोगकर्ता नाम और पासवर्ड लेगा।
कुछ बुनियादी सत्यापन जोड़ने के लिए, जांचें कि क्या उपयोगकर्ता डेटाबेस में मौजूद है, और दिए गए पासवर्ड की तुलना अपने डेटाबेस से करें ताकि यह सुनिश्चित हो सके कि यह मेल खाता है। यदि यह मौजूद है, तो उपयोगकर्ता को request.user
. में वापस कर दें वस्तु - अन्यथा, शून्य लौटें।
auth.service.ts
import { Injectable, NotAcceptableException } from '@nestjs/common';
import { UsersService } from 'src/users/users.service';
import * as bcrypt from 'bcrypt';
@Injectable()
export class AuthService {
constructor(private readonly usersService: UsersService) {}
async validateUser(username: string, password: string): Promise<any> {
const user = await this.usersService.getUser(username);
const passwordValid = await bcrypt.compare(password, user.password)
if (!user) {
throw new NotAcceptableException('could not find the user');
}
if (user && passwordValid) {
return {
userId: user.id,
userName: user.username
};
}
return null;
}
}
आगे जाकर, एक नई फ़ाइल बनाएँ और उसका नाम local.strategy.ts
. रखें . यह फ़ाइल Passport.js
. से रणनीति का प्रतिनिधित्व करेगी , जिसे आपने पहले स्थापित किया था, वह local strategy
. है . और इसके भीतर, रणनीति में पास करें, जो कि Strategy
. है passport-local
. से ।
एक कंस्ट्रक्टर बनाएं और AuthService
इंजेक्ट करें , super()
पर कॉल करें तरीका; super()
. को कॉल करना सुनिश्चित करें विधि।
local.strategy.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { AuthService } from './auth.service';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly authService: AuthService) {
super();
}
async validate(username: string, password: string): Promise<any> {
const userName = username.toLowerCase();
const user = await this.authService.validateUser(userName, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
अपने auth.module.ts
. पर वापस जाएं फ़ाइल। फिर PassportModule
add जोड़ें आयात करने के लिए और LocalStrategy
प्रदाताओं के लिए।
auth.module.ts
import { Module } from "@nestjs/common"
import { PassportModule } from "@nestjs/passport"
import { UsersModule } from "src/users/users.module"
import { AuthService } from "./auth.service"
import { LocalStrategy } from "./local.strategy"
@Module({
imports: [UsersModule, PassportModule],
providers: [AuthService, LocalStrategy],
})
export class AuthModule {}
अब, अपने users.controller.ts
. में लॉगिन रूट जोड़ें :
users.controller.ts
import {
Body,
Controller,
Post,
Request,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//post / signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
//Post / Login
@Post('/login')
login(@Request() req): any {
return {User: req.user,
msg: 'User logged in'};
}
}
अब जब आपके पास ये सब स्थापित हो गए हैं, तब भी आप किसी उपयोगकर्ता में लॉग इन नहीं कर सकते क्योंकि लॉगिन मार्ग को ट्रिगर करने के लिए कुछ भी नहीं है। यहां, इसे हासिल करने के लिए गार्ड्स का उपयोग करें।
एक फाइल बनाएं और उसे नाम दें local.auth.guard.ts
, फिर एक वर्ग LocalAuthGuard
जो AuthGuard
. का विस्तार करता है NestJS/passport
. से , जहां आप रणनीति का नाम प्रदान करेंगे और अपनी रणनीति के नाम पर पास करेंगे, local
।
local.auth.guard.ts.
import { Injectable } from "@nestjs/common"
import { AuthGuard } from "@nestjs/passport"
@Injectable()
export class LocalAuthGuard extends AuthGuard("local") {}
UseGuard
जोड़ें users.controller.ts
. में अपने लॉगिन रूट के लिए डेकोरेटर फ़ाइल, और LocalAuthGuard
. में पास करें ।
users.controller.ts
import {
Body,
Controller,
Post,
UseGuards,
Request,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { LocalAuthGuard } from 'src/auth/local.auth.guard';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//post / signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
//Post / Login
@UseGuards(LocalAuthGuard)
@Post('/login')
login(@Request() req): any {
return {User: req.user,
msg: 'User logged in'};
}
}
अंत में, आप एक पंजीकृत उपयोगकर्ता नाम और पासवर्ड के साथ एक उपयोगकर्ता में लॉग इन कर सकते हैं।
प्रमाणीकरण मार्गों की रक्षा करें
आपने सफलतापूर्वक उपयोगकर्ता प्रमाणीकरण सेट कर लिया है। अब, केवल प्रमाणित उपयोगकर्ताओं तक पहुंच सीमित करके अपने मार्गों को अनधिकृत पहुंच से बचाएं। अपने users.controller.ts
. पर जाएं फ़ाइल, और दूसरा मार्ग जोड़ें - इसे 'संरक्षित' नाम दें और इसे req.user
लौटाएं वस्तु।
users.controller.ts
import {
Body,
Controller,
Get,
Post,
UseGuards,
Request,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { LocalAuthGuard } from 'src/auth/local.auth.guard';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
//Post / Login
@UseGuards(LocalAuthGuard)
@Post('/login')
login(@Request() req): any {
return {User: req.user,
msg: 'User logged in'};
}
// Get / protected
@Get('/protected')
getHello(@Request() req): string {
return req.user;
}
}
उपरोक्त कोड में संरक्षित मार्ग उपयोगकर्ता के विवरण को वापस करने के बजाय एक खाली वस्तु लौटाएगा जब एक लॉग-इन उपयोगकर्ता इसके लिए अनुरोध करता है क्योंकि यह पहले ही लॉगिन खो चुका है।
इसे क्रमबद्ध करने के लिए, यह वह जगह है जहां सत्र-आधारित प्रमाणीकरण आता है।
सत्र-आधारित प्रमाणीकरण में, जब कोई उपयोगकर्ता लॉग इन करता है, तो उपयोगकर्ता को सत्र में सहेजा जाता है ताकि लॉगिन के बाद उपयोगकर्ता द्वारा बाद में कोई भी अनुरोध सत्र से विवरण प्राप्त कर सके और उपयोगकर्ता को आसान पहुंच प्रदान कर सके। जब उपयोगकर्ता लॉग आउट करता है तो सत्र समाप्त हो जाता है।
सत्र-आधारित प्रमाणीकरण शुरू करने के लिए, निम्न आदेश का उपयोग करके एक्सप्रेस-सत्र और NestJS प्रकार स्थापित करें:
npm install express-session @types/express-session
जब इंस्टॉलेशन पूरा हो जाए, तो अपने main.ts
. पर जाएं फ़ाइल, अपने आवेदन की जड़, और वहां कॉन्फ़िगरेशन करें।
passport
से सब कुछ आयात करें और express-session
, फिर पासपोर्ट इनिशियलाइज़ और पासपोर्ट सत्र जोड़ें।
अपनी गुप्त कुंजी को अपने परिवेश चर में रखना बेहतर है।
main.ts
import { NestFactory } from "@nestjs/core"
import { AppModule } from "./app.module"
import * as session from "express-session"
import * as passport from "passport"
async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.use(
session({
secret: "keyboard",
resave: false,
saveUninitialized: false,
})
)
app.use(passport.initialize())
app.use(passport.session())
await app.listen(3000)
}
bootstrap()
एक नई फ़ाइल जोड़ें, authenticated.guard.ts
, आपके auth
. में फ़ोल्डर। और एक नया गार्ड बनाएं जो यह जांचता है कि अनुरोध करने वाले उपयोगकर्ता के लिए कोई सत्र है या नहीं - इसे नाम दें authenticatedGuard
।
authenticated.guard.ts
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common"
@Injectable()
export class AuthenticatedGuard implements CanActivate {
async canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest()
return request.isAuthenticated()
}
}
उपरोक्त कोड में, अनुरोध संदर्भ से प्राप्त किया गया है और प्रमाणित होने पर जांचा गया है। isAuthenticated()
passport.js
. से आता है खुद ब खुद; इसे कहते हैं। "अरे! क्या इस उपयोगकर्ता के लिए कोई सत्र मौजूद है? यदि हां, तो जारी रखें।"
लॉगिन को ट्रिगर करने के लिए, अपने users.controller.ts
. में फ़ाइल:
- आयात
authenticated
authenticated.guard.ts
. से; useGuard
जोड़ेंprotected
. के लिए डेकोरेटर रास्ता; और,- पास
authenticatedGuard
।
users.controller.ts
import {
Body,
Controller,
Get,
Post,
UseGuards,
Request,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { AuthenticatedGuard } from 'src/auth/authenticated.guard';
import { LocalAuthGuard } from 'src/auth/local.auth.guard';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
//Post / Login
@UseGuards(LocalAuthGuard)
@Post('/login')
login(@Request() req): any {
return {User: req.user,
msg: 'User logged in'};
}
//Get / protected
@UseGuards(AuthenticatedGuard)
@Get('/protected')
getHello(@Request() req): string {
return req.user;
}
}
इस बिंदु पर, यह अभी भी विफल रहता है क्योंकि आपने केवल express-session
को कॉन्फ़िगर किया है लेकिन इसे लागू नहीं किया।
जब कोई उपयोगकर्ता लॉग इन करता है, तो आपको उपयोगकर्ता को सत्र में सहेजना होगा ताकि उपयोगकर्ता सत्र के साथ अन्य मार्गों तक पहुंच सके।
एक बात का ध्यान रखें कि डिफ़ॉल्ट रूप से, express-session
पुस्तकालय सत्र को वेब सर्वर की स्मृति में संग्रहीत करता है।
सत्र में जाने से पहले, आपको उपयोगकर्ता को क्रमबद्ध करने की आवश्यकता है। जैसे ही यह सत्र से बाहर आता है, उपयोगकर्ता को deserialize करें।
इसलिए, सीरिएलाइज़र और डिसेरिएलाइज़र के लिए ऑथ फ़ोल्डर में एक नई फ़ाइल बनाएँ, इसे session.serializer.ts
नाम दें। ।
इस बिंदु पर, हमारे आवेदन का आकार src
फ़ोल्डर इस तरह दिखना चाहिए।
└───src
│ └───auth
│ │ └───auth.module.ts
│ │ └───auth.service.ts
│ │ └───authenticated.guard.ts
│ │ └───local.auth.guard.ts
│ │ └───local.strategy.ts
│ │ └───session.serializer.ts
│ └───users
│ │ └───users.controller.ts
│ │ └───users.model.ts
│ │ └───users.module.ts
│ │ └───users.service.ts
│ └───app.controller.ts
│ └───app.module.ts
│ └───app.service.ts
│ └───main.ts
session.serializer.ts
import { Injectable } from "@nestjs/common"
import { PassportSerializer } from "@nestjs/passport"
@Injectable()
export class SessionSerializer extends PassportSerializer {
serializeUser(user: any, done: (err: Error, user: any) => void): any {
done(null, user)
}
deserializeUser(
payload: any,
done: (err: Error, payload: string) => void
): any {
done(null, payload)
}
}
अपने auth.module.ts
. पर वापस जाएं फ़ाइल, SessionSerializer
प्रदान करें , और register
जोड़ें PassportModule
. के लिए विधि ।
auth.module.ts
import { Module } from "@nestjs/common"
import { PassportModule } from "@nestjs/passport"
import { UsersModule } from "src/users/users.module"
import { AuthService } from "./auth.service"
import { LocalStrategy } from "./local.strategy"
import { SessionSerializer } from "./session.serializer"
@Module({
imports: [UsersModule, PassportModule.register({ session: true })],
providers: [AuthService, LocalStrategy, SessionSerializer],
})
export class AuthModule {}
Add some codes within the LocalAuthGuard
in the local.auth.guard.ts
फ़ाइल।
Call the login
method in super
and pass in the request to trigger the actual login by creating a session. If you want to use sessions, you must remember to trigger the super.login()
।
local.auth.guard.ts
import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
async canActivate(context: ExecutionContext) {
const result = (await super.canActivate(context)) as boolean;
const request = context.switchToHttp().getRequest();
await super.logIn(request);
return result;
}
}
If you log in now, you will see the session ID stored in a cookie, which is just a key to the session store, and the cookie gets saved in the browser. The cookie is automatically attached to the rest of the request.
Now that the session is working, you can access the protected route; it will return the expected user’s details.
Logout Users
As mentioned earlier, once a user logs out, you destroy all sessions.
To log out a user, go to the users.controller.ts
file, add a logout route, and call the req.session.session()
method. You can return a message notifying that the user’s session has ended.
import {
Body,
Controller,
Get,
Post,
UseGuards,
Request,
} from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { AuthenticatedGuard } from 'src/auth/authenticated.guard';
import { LocalAuthGuard } from 'src/auth/local.auth.guard';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
//signup
@Post('/signup')
async addUser(
@Body('password') userPassword: string,
@Body('username') userName: string,
) {
const saltOrRounds = 10;
const hashedPassword = await bcrypt.hash(userPassword, saltOrRounds);
const result = await this.usersService.insertUser(
userName,
hashedPassword,
);
return {
msg: 'User successfully registered',
userId: result.id,
userName: result.username
};
}
//Post / Login
@UseGuards(LocalAuthGuard)
@Post('/login')
login(@Request() req): any {
return {User: req.user,
msg: 'User logged in'};
}
//Get / protected
@UseGuards(AuthenticatedGuard)
@Get('/protected')
getHello(@Request() req): string {
return req.user;
}
//Get / logout
@Get('/logout')
logout(@Request() req): any {
req.session.destroy();
return { msg: 'The user session has ended' }
}
}
So, once you log out, it returns a message notifying you that the user session has ended. The code for this tutorial is hosted here on my Github repository.
Test Your Application
You have successfully implemented user signup, authentication, and protected the route to enable authorized access only.
It’s time to test the application. If everything is in order, your server should be running. Else, restart your server with the following command:
npm run start:dev
Head over to your Postman. And let’s finally test our application.
Sign Up As a User
Log In As a User
Logged-in User’s Cookie ID
Request the Protected Route
User Logout
Alternatively, Implement User Authentication with LoginRadius
LoginRadius provides a variety of registration and authentication services to assist you in better connecting with your consumers.
On any web or mobile application, LoginRadius is the developer-friendly Identity Platform that delivers a complete set of APIs for authentication, identity verification, single sign-on, user management, and account protection capabilities like multi-factor authentication.
To implement LoginRadius in your NestJS application, follow this tutorial:NestJS User Authentication with LoginRadius API.
Conclusion
बधाई हो! In this tutorial, you've learned how to implement session-based authentication in a NestJS application with the MongoDB database. You've created and authenticated a user and protected your routes from unauthorized access.
You can access the sample code used in this tutorial on GitHub.
<ब्लॉकक्वॉट>नोट: Session storage is saved by default in 'MemoryStore,' which is not intended for production use. So, while no external datastore is required for development, once in production, a data store such as Redis or another is suggested for stability and performance. You can learn more about session storage here.