نحوه استفاده از JWT Authentication در NodeJs/NextJs

JWT چیست؟
نشانه وب JSON (JWT) که “jot” تلفظ می شود، یک استاندارد باز (RFC 7519) است که یک روش فشرده و مستقل برای انتقال ایمن اطلاعات بین طرفین به عنوان یک شی JSON تعریف می کند. (تعریف از auth0.com)
در اصطلاح ساده، اساسا راهی برای تبدیل شی JSON به یک رشته با استفاده از کلیدی که ما به آن ارائه می کنیم، ارائه می دهد.
خروجی JWT، رشته به دست آمده، برای انتقال امن اطلاعات بین کلاینت و سرور استفاده می شود.
می توانیم برای احراز هویت استفاده کنیم که بیشتر از طریق انجام می شود میان افزار
Middleware چیست؟
گاهی اوقات لازم است درخواست ارسال شده توسط مشتری را اصلاح کنیم. فرض کنید مشتری شناسه کاربری خودش را برای ما ارسال می کند، اما ما اطلاعاتی مانند ایمیل مربوط به مشتری را برای دیگری نمی دانیم.
یکی از کارهایی که انجام می دهد، واکشی داده ها در داخل است عملکرد کنترل کننده درخواست (به عنوان app.post تابع کنترل درخواست در nodejs/express است). همه اینها خوب است، اما مشکل این نوع مدیریت این است که تا حدودی کد را می سازد ناپاک و تاثیر می گذارد خوانایی از کد
راه دیگر این است که یک میان افزار بسازید که یک تابع مجزا به غیر از تابع رسیدگی کننده درخواست و ترجیحاً در فایل جداگانه خواهد بود. Middleware 3 آرگومان، درخواست، پاسخ و بعدی را می پذیرد.
export const authenticate = (req, res, next)=>{
...
}
درخواست و پاسخ همانند توابع کنترل کننده درخواست هستند، یعنی درخواست حاوی داده های ارسال شده توسط مشتری است و از پاسخ برای ارسال پاسخ به مشتری استفاده می شود.
آرگومان بعدی تابعی است که وقتی فراخوانی می شود، درخواست را به کنترل کننده بعدی منتقل می کند، یعنی یا تابع میان افزار بعدی یا تابع کنترل کننده درخواست نهایی. بستگی به این دارد که چگونه میان افزارها را براساس عملکرد کنترل کننده درخواست زنجیره ای کنید.
مثلا:
app.get(authenticate, async(req, res)=>{
...
}
در مورد بالا، ما میان افزار احراز هویت و سپس تابع رسیدگی کننده درخواست نهایی خود را فراخوانی می کنیم.
عملکرد میانافزار احراز هویت در بالا به شکل زیر است:
export const authenticate = (req, res, next)=>{
if(<authentication successful>){
next()
}
else{
return res.status(401).json({success: false, message: "You are not logged in"})
}
نحوه استفاده از JWT در کنار میان افزارها
بنابراین اول، زمانی که کاربر ثبت نام یا وارد شدن، ما باید JWT را با جزئیات کاربر، عمدتاً با شناسه کاربر، تولید کنیم.
این چیزی است که ثبت نام من به نظر می رسد:
import Users from "../../backend/models/Users"
import dbConnect from "../../backend/utils/dbConnect"
import { signToken } from "../../backend/utils/jwt"
export default async function handler(req, res) {
if(req.method != "POST")
return res.status(404).json({success: false, message: "Method Not Found"})
if(!req.body.email || !req.body.password || !req.body.name)
return res.status(400).json({success: false, message: "Please Provide Email, Password and Name"})
await dbConnect()
const {email, password, name} = req.body
try{
let userFound = await Users.findOne({email})
if(userFound)
return res.status(401).json({success: false, message: "Email Already Registered"})
let user = new Users({email, password, name})
await user.save()
let jwtToken = signToken({id: user.id}, process.env.NEXT_PUBLIC_JWT_SECRET)
return res.status(200).json({success: true, data: {token: jwtToken}})
}
catch(err){
console.log(err)
return res.status(500).json({succes: false, message: "Some Error Occured In Server, Error: " + err})
}
}
خط: let jwtToken = signToken({id: user.id}, process.env.NEXT_PUBLIC_JWT_SECRET)
یک رشته (jwt toke) را بر اساس شی ارائه شده به عنوان آرگومان اول و کلید ارائه شده به عنوان آرگومان دوم برمی گرداند (process.env.NEXT_PUBLIC_JWT_SECRET کلید موجود در فایل .env، یک متغیر محیطی است)
ما باید توکن jwt (رشته ای که توسط signToken برگردانده شده است) را برای مشتری ارسال کنیم و مشتری آن را به عنوان کوکی ذخیره می کند. و با هر درخواست، مشتری این jwt را به عنوان مجوز در هدر به عنوان ‘Bearer jwt_token’ ارسال می کند.
تابع میان افزار احراز هویت ما به این صورت است:
import jwt from 'jsonwebtoken'
export const authenticate = (req, res, next)=>{
if(!req.headers.authorization)
return res.status(401).json({success: false, message: "User Not Authorized"})
let token = req.headers.authorization
// Bearer token
token = token.split(" ")[1]
try{
let user = jwt.verify(token, process.env.NEXT_PUBLIC_JWT_SECRET)
req.user = user
next()
}
catch(err){
return res.status(401).json({success: false, message: "User Not Autorized"})
}
}
می بینید که تابع میان افزار احراز هویت در حال استخراج است req.headers.authorization که حاوی رمز وب JSON ما است که توسط مشتری در این قالب ارسال شده است: “Bearer jwt_token”
بنابراین، با تقسیم رشته با “فضای سفید” به عنوان جداکننده و استخراج رشته در شاخص دوم، که JWT ما است، نشانه را دریافت می کنیم.
اکنون آن را با استفاده از تابع jwt.verify تأیید می کنیم، که توکن jwt را به عنوان آرگومان اول و کلید مخفی را به عنوان آرگومان دوم می گیرد.
این شیئی را که هنگام ایجاد توکن jwt ارائه کرده بودیم برمی گرداند.
ما از این شیء استفاده میکنیم و در درخواست ذخیره میکنیم تا بتوان توسط تابع کنترلکننده درخواست بعدی به سادگی از آن استفاده کرد:req.user = user
و سپس ما تماس خواهیم گرفت next()
در صورتی که jwt توکن ارائه شده توسط کلاینت را تأیید نکند، ما به سادگی در تابع میانافزار احراز هویت، پاسخ خواهیم داد.return res.status(401).json({success: false, message: "User Not Autorized"})
همین است، امیدوارم به شما کمک کرده باشد