چطور از سرویس های back-end مان محافظت کنیم؟ چه GET باشد چه POST ، UPDATE ، PATCH و DELETE
- نفیسه افقی 1 سال قبل سوال کرد
- شما باید برای ارسال دیدگاه وارد شوید
فرض کنید سرویس های مختلفی (GET,POST,DELETE,PATCH,UPDATE) برای back-end نوشتیم، اگر آدرس و پورت back دست هر شخصی بیفتد ، می تواند سرویس های شما را فراخوانی کند (مثلاً پستی یا همه پست ها را حذف کند، آپدیت کند و …)
برای جلوگیری از دسترسی افراد احراز هویت نشده باید چکار کنیم؟
برای این کار باید برای هر سرویس Guard تعریف کنیم. با گذاشتن decorator ای بنام UseGuards@
بالای هر تایع controller می توانیم کاری کنیم که آن تابع تنها پس از احراز هویت اجرا شود. برای احراز هویت هم الگوریتم های مختلفی وجود دارد که ما از یکی از ممعروفترین آن ها یعنی JWT
استفاده می کنیم. نام الگوریتمی که استفاده می کنیم باید کنار decorator نوشته شود. یعنی تابع deleteای که داخل controller نوشتیم ، به این صورت در می آید:
@UseGuards(JwtAuthGuard)
@Delete(":_id")
async deletePage(
@Param("_id") _id: string) {
return await this.pagesService.deletePage(_id);
}
JWT چطور احراز هویت می کند؟
jwt مخفف json web token
است و بدین صورت عمل می کند که وقتی کاربر احراز هویت شد و لاگین کرد، یک توکن با محتوایی که می خواهیم (مثلا شامل id و role کاربر، یا هر داده ای که می خواهیم) می سازیم ، رمزنگاری می کنیم و به front-end می فرستیم. قسمت front-end ، این توکن رمزنگاری شده را در local storage ذخیره می کند و هر زمان خواست http request ای به back-end بفرستد، این توکن را داخل header قرار می دهد و می فرستد. back-end هم این توکن را می گیرد، باز می کند و اگر درست بود، درخواست احراز هویت می شود و تابع مذکور اجرا می شود. در اینصورت تنها کسانی می توانند تابع ما را اجرا کنند که توکن داشته باشند.
*دقت کنید که می توانیم برای توکن تاریخ انقضا تعریف کنیم. (مثلاً اگر کاربر داخل کافی نت لاگین کرده و توکن آنجا ذخیره شده باشد، ممکن است شخص دیگه ای به توکن دسترسی پیدا کن)
برای استفاده از jwt ، لازم است تا کتابخانه های زیر را نصب کنید:
npm install @nestjs/jwt
npm install passport-jwt
npm install jsonwebtoken
چطور بعد از لاگین کاربر، توکن بسازیم و ارسال کنیم؟
در تابعی که برای لاگین کاربر نوشته اید، jsonwebtoken
را ایمپورت کنید:
import * as jwt from 'jsonwebtoken';
و به صورت زیر یک توکن بسازید و امضایش کنید:
async tokenGenerator(payload:AuthPayload)
{
return jwt.sign(payload,process.env.ACCESS_JWT_SECRET);
}
*AuthPayload
مدلی است که برای توکن تعریف کرده ایم. شما هر داده ای از کاربر را می توانید به عنوان توکن تعریف کنید. مثلا ما AuthPayload
را در فولدری بنام auth
و بدین صورت تعریف کرده ایم:
export class AuthPayload
{
user_id:string;
role:string;
}
*payload به معنای توکنی است که رمزش باز شده.
*اکیدا توصیه می شود که کلیدی که توکن به وسیله آن رمزنگاری شده و باز می شود را در فایل env. و به عنوان environment variable ذخیره کنید.
*وقتی کاربر با موفقیت لاگین شد، باید این توکن را به فرانت ارسال کنیم و فرانت هم باید آن ها در local storage ذخیره کند.
چطور JwtAuthGuard
را بسازیم؟
فولدری بنام auth بسازیم و داخل آن باید دو فایل اصلی برای guard و strategy داشته باشید.
فایل jwt-auth-guard.ts
را بدین صورت تعریف کنید:
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt')
{
}
فایل jwt-strategy.ts
را بدین صورت تعریف کنید:
import {PassportStrategy} from "@nestjs/passport";
import {ExtractJwt, Strategy} from "passport-jwt";
import { Injectable} from "@nestjs/common";
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.ACCESS_JWT_SECRET,
})
}
async validate(payload: any) {
return {user_id: payload.user_id, role: payload.role}
}
}
حالا کافی است تا در فایل کنترلری که می خواهیم از guard استفاده کنیم، JwtAuthGuard
را ایمپورت کنیم:
import { JwtAuthGuard } from "src/auth/jwt-auth-guard";
و بالای تابع موردنظرمان، از decorator زیر استفاده کنیم:
@UseGuards(JwtAuthGuard)
*بهتر است auth
را بصورت ماژول در آورید (حتی می توانید تابع تولید کننده توکن tokenGenerator
، را داخل AuthService
قرار دهید):
import { Module } from "@nestjs/common"
import { PassportModule } from "@nestjs/passport"
import { UsersModule } from "src/users/users.module"
import { AuthService } from "./auth.service"
@Module({
imports: [PassportModule.register({ session: true })],
providers: [AuthService],
})
export class AuthModule {}
*دقت کنید که باید داخل فایل app.module
هم jwt را ایمپورت کرده و به عنوان ماژل اضافه کنید:
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './auth/strategy/jwt-strategy';
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({secret: process.env.ACCESS_JWT_SECRET}),
AuthModule],
controllers: [AppController],
providers: [AppService,JwtStrategy],
})
export class AppModule {}
چطور در فرانت ، توکن را داخل http request قرار دهیم و ارسال کنیم؟
به صورت زیر می توانید header درخواستتان را بسازید (توکن را از local storage بگیرید و داخل آن قرار دهید):
const token = JSON.parse(localStorage.getItem('Token'));
const config = { headers: {"Content-Type": "application/json",Authorization: `Bearer ${token}`} }
حالا header را داخل درخواست axios
قرار دهید:
axios.patch("BACK_END_ADRESS", data, config);
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین ویرایش 1 سال قبل
- شما باید برای ارسال دیدگاه وارد شوید