محمود سعداوي2 نشر 3 أغسطس أرسل تقرير نشر 3 أغسطس السلام عليكم. أرجو مساعدتي في التحقق من البيانات بواسطة cookie و jwt في مشروع Nextjs 14. تظهر لي رسالة الخطأ التالية { "message": "Not authorized, no token" } للتوضيح: في البداية قمت بتوليد token و cookie utils/generateToken import jwt from 'jsonwebtoken' const generateToken = (id) => { const token = jwt.sign({ userId: id }, process.env.JWT_SECRET, { expiresIn: '1d' }); return token; } const setTokenCookie = (response, token) => { response.cookies.set('token', token, { httpOnly: true, secure: process.env.NODE_ENV !== 'development', sameSite: 'strict', maxAge: 60*60*24 }); } export { generateToken, setTokenCookie }; ثم قمت بإنشاء الحساب وتسجيل الدخول (سوف أعرض تسجيل الدخول لأنهما مشابهين كثيرا) app/api/auth/login/route.js import connectDB from "@/config/connectDB"; import User from "@/models/User"; import { generateToken, setTokenCookie } from "@/utils/generateToken"; import bcrypt from "bcryptjs"; import { NextResponse } from "next/server"; /** * Method: POST * route : /api/auth/login */ export const POST = async (request) => { await connectDB(); try { const { email, password } = await request.json(); const user = await User.findOne({ email }); const isMatch = await bcrypt.compare(password, user.password) if (!user || !isMatch) { return new NextResponse("Invalid Credentials", { status: 400 }) } if (user) { const token = generateToken(user._id); const response = new NextResponse( JSON.stringify({ user: user.email }), { status: 200 } ); setTokenCookie(response, token); return response; } else { return new NextResponse("Failed to create user", { status: 500 }); } } catch (error) { console.log(error); return new Response("Something went wrong => Register User", { status: 500, }); } }; ثم قمت بتحديد الوسائط middlewares/protect.js import User from "@/models/User"; import { cookies } from "next/headers"; const protect = async (request) => { const cookieStore = cookies() const token = cookieStore.get('jwt')?.value; if (!token) { throw new Error('Not authorized, no token'); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId) if (!user) { throw new Error('Not authorized, user not found'); } return user; } catch (error) { console.error(error); throw new Error('Not authorized, token failed'); } }; export default protect; في النهاية لتجربة التحقق قمت ب: app/api/auth/me/route.js import connectDB from "@/config/connectDB" import protect from "@/middleware/protect" import User from "@/models/User" import { NextResponse } from "next/server" /** * Test If Route Is Protected */ export const GET = async (request) => { await connectDB() try { const user = await protect(request) const me = await User.findById(user._id ) return NextResponse.json(me, { status: 200 }) } catch (error) { return NextResponse.json({ message: error.message }, { status: 401 }); } } الرجاء مساعدتي في تحديد سبب فشل التحقق من البيانات. شكرا. 4 اقتباس
0 Mustafa Mahmoud7 نشر 3 أغسطس أرسل تقرير نشر 3 أغسطس المشكلة في middlewares/protect.js في هذا السطر const token = cookieStore.get('jwt')?.value; حيث تريد الوصول للكوكيز باسم jwt وهي غير موجودة لأنك في utils/generateToken عند وضع الكوكيز كانت باسم token وليس jwt response.cookies.set('token', token, { ^^^^^ httpOnly: true, secure: process.env.NODE_ENV !== 'development', sameSite: 'strict', maxAge: 60*60*24 }); لذا نقوم بتعديل هذا السطر في middlewares/protect.js ليصبح ليتم الوصول للكوكيز بشكل صحيح const token = cookieStore.get('token')?.value; وأيضا قم باستيراد الحزمة jwt أعلى ملف middlewares/protect.js ليتم الوصول منها للدالة ()verify حيث أننا ننريدها ليتم فك تشفير token بعد ذلك. import jwt from 'jsonwebtoken' بالتوفيق... 1 اقتباس
0 ياسر مسكين نشر 3 أغسطس أرسل تقرير نشر 3 أغسطس بناء على الشيفرة خاصتك، ففي ملف generateToken.js، تقوم بتعيين اسم الـ cookie كـ 'token' هنا: response.cookies.set('token', token, { }); لكن في ملف protect.js، تحاول الحصول على الـ cookie باسم 'jwt': const token = cookieStore.get('jwt')?.value; لذا يجب أن يكون اسم الـ cookie متطابقاً في كلا الموضعين. كما أني لا أرى أنك قمت باستيراد مكتبة jsonwebtoken في ملف protect.js لذا يجب إضافة هذا الاستيراد: import jwt from 'jsonwebtoken'; أما فيما يخص كيفية التعامل مع الـ response في ملف generateToken.js ففي الدالة setTokenCookie، تستخدم response.cookies.set، لكن في Next.js 14، يجب استخدام cookies() من next/headers كالتالي: import { cookies } from 'next/headers'; const setTokenCookie = (token) => { cookies().set('token', token, { httpOnly: true, secure: process.env.NODE_ENV !== 'development', sameSite: 'strict', maxAge: 60*60*24 }); } أما في ملف login/route.js، يجب تعديل كيفية استخدام setTokenCookie إلى: if (user) { const token = generateToken(user._id); setTokenCookie(token); return NextResponse.json({ user: user.email }, { status: 200 }); } else { return new NextResponse("Failed to create user", { status: 500 }); } واحرص على أن تكون قمت بتعريف ال JWT_SECRET في ملف .env، أرجو تصحيح الأخطاء التالية مع إرفاق صورة للخطأ الذي تواجهه في حالة استمرار المشكلة. 1 اقتباس
0 محمود سعداوي2 نشر 3 أغسطس الكاتب أرسل تقرير نشر 3 أغسطس بتاريخ 9 دقائق مضت قال Mustafa Mahmoud7: المشكلة في middlewares/protect.js في هذا السطر const token = cookieStore.get('jwt')?.value; حيث تريد الوصول للكوكيز باسم jwt وهي غير موجودة لأنك في utils/generateToken عند وضع الكوكيز كانت باسم token وليس jwt response.cookies.set('token', token, { ^^^^^ httpOnly: true, secure: process.env.NODE_ENV !== 'development', sameSite: 'strict', maxAge: 60*60*24 }); لذا نقوم بتعديل هذا السطر في middlewares/protect.js ليصبح ليتم الوصول للكوكيز بشكل صحيح const token = cookieStore.get('token')?.value; وأيضا قم باستيراد الحزمة jwt أعلى ملف middlewares/protect.js ليتم الوصول منها للدالة ()verify حيث أننا ننريدها ليjم فك تشفير token بعد ذلك. import jwt from 'jsonwebtoken' بالتوفيق... مارأيك بطريقة كتابة الكود. هل تخضع لbest practice 1 اقتباس
0 Mustafa Mahmoud7 نشر 3 أغسطس أرسل تقرير نشر 3 أغسطس بتاريخ 25 دقائق مضت قال محمود سعداوي2: مارأيك بطريقة كتابة الكود. هل تخضع لbest practice بنسبة كبيرة نعم فأنت تقوم بالأتي:- 1- تقسيم الكود الخاص بك إلى دوال صغيرة ليسهل التعامل معها. 2- التعامل مع الأخطاء وإرسال رسالة بالخطأ في كل جزء يسهل العملية أيضا. 3 -إرسال كود حالة مثل (200 ، 500، 201) جيدا أيضا. 4-طريقة التسمية وكل شئ يقوم بما تم تسميته به جيد. 5- كتباتك لتوثيق الدالة مثل هذا جيد ضعه لكل الدوال أيضا. /** * Method: POST * route : /api/auth/login * */ استمر على هذا النهج ومع الوقت ستتطور أكثر وأكثر. بالتوفيق.. 1 اقتباس
السؤال
محمود سعداوي2
السلام عليكم.
أرجو مساعدتي في التحقق من البيانات بواسطة cookie و jwt في مشروع Nextjs 14.
تظهر لي رسالة الخطأ التالية
{ "message": "Not authorized, no token" }
للتوضيح:
في البداية قمت بتوليد token و cookie
utils/generateToken
import jwt from 'jsonwebtoken' const generateToken = (id) => { const token = jwt.sign({ userId: id }, process.env.JWT_SECRET, { expiresIn: '1d' }); return token; } const setTokenCookie = (response, token) => { response.cookies.set('token', token, { httpOnly: true, secure: process.env.NODE_ENV !== 'development', sameSite: 'strict', maxAge: 60*60*24 }); } export { generateToken, setTokenCookie };
ثم قمت بإنشاء الحساب وتسجيل الدخول (سوف أعرض تسجيل الدخول لأنهما مشابهين كثيرا)
app/api/auth/login/route.js
import connectDB from "@/config/connectDB"; import User from "@/models/User"; import { generateToken, setTokenCookie } from "@/utils/generateToken"; import bcrypt from "bcryptjs"; import { NextResponse } from "next/server"; /** * Method: POST * route : /api/auth/login */ export const POST = async (request) => { await connectDB(); try { const { email, password } = await request.json(); const user = await User.findOne({ email }); const isMatch = await bcrypt.compare(password, user.password) if (!user || !isMatch) { return new NextResponse("Invalid Credentials", { status: 400 }) } if (user) { const token = generateToken(user._id); const response = new NextResponse( JSON.stringify({ user: user.email }), { status: 200 } ); setTokenCookie(response, token); return response; } else { return new NextResponse("Failed to create user", { status: 500 }); } } catch (error) { console.log(error); return new Response("Something went wrong => Register User", { status: 500, }); } };
ثم قمت بتحديد الوسائط
middlewares/protect.js
import User from "@/models/User"; import { cookies } from "next/headers"; const protect = async (request) => { const cookieStore = cookies() const token = cookieStore.get('jwt')?.value; if (!token) { throw new Error('Not authorized, no token'); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); const user = await User.findById(decoded.userId) if (!user) { throw new Error('Not authorized, user not found'); } return user; } catch (error) { console.error(error); throw new Error('Not authorized, token failed'); } }; export default protect;
في النهاية لتجربة التحقق قمت ب:
app/api/auth/me/route.js
import connectDB from "@/config/connectDB" import protect from "@/middleware/protect" import User from "@/models/User" import { NextResponse } from "next/server" /** * Test If Route Is Protected */ export const GET = async (request) => { await connectDB() try { const user = await protect(request) const me = await User.findById(user._id ) return NextResponse.json(me, { status: 200 }) } catch (error) { return NextResponse.json({ message: error.message }, { status: 401 }); } }
الرجاء مساعدتي في تحديد سبب فشل التحقق من البيانات. شكرا.
4 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.