30 نوفمبر 2025·4 دقيقة قراءة

حراس توجيه Vue 3 للوصول حسب الأدوار: أنماط عملية

شرح حراس التوجيه في Vue 3 للوصول بناءً على الأدوار بأساليب عملية: قواعد meta في المسارات، إعادة توجيه آمنة، صفحات بديلة ودية 401/403، وتجنّب تسريب البيانات.

حراس توجيه Vue 3 للوصول حسب الأدوار: أنماط عملية

ما الذي تحله حراس المسار فعلاً (وماذا لا تفعل)

حراس المسار تقوم بمهمة واحدة بشكل جيد: التحكم في التنقل. هم يقررون ما إذا كان يمكن لشخص ما دخول مسار، وأين ترسله إذا لم يستطع. هذا يحسن تجربة المستخدم، لكنه ليس بديلاً عن الأمان.

إخفاء عنصر في القائمة هو مجرد تلميح، وليس تفويضاً. لا يزال بإمكان الأشخاص كتابة عنوان URL، أو تحديث صفحة عميقة، أو فتح إشارة مرجعية. إذا كان الحماية الوحيدة لديك هي "الزر غير مرئي"، فلا حماية حقيقية لديك.

تلمع الحراس عندما تريد من التطبيق أن يتصرف بشكل متسق أثناء حظر صفحات لا ينبغي عرضها، مثل مناطق المشرف، الأدوات الداخلية، أو بوابات العملاء القائمة على الأدوار.

تساعدك الحراس على:

  • حظر الصفحات قبل عرضها
  • إعادة التوجيه إلى تسجيل الدخول أو لقيمة افتراضية آمنة
  • إظهار شاشة 401/403 واضحة بدلًا من عرض مكسور
  • تجنب حلقات التنقل العرضية

ما لا تستطيع الحراس فعله بمفردها هو حماية البيانات. إذا أعاد API بيانات حساسة إلى المتصفح، فلا يزال المستخدم قادراً على استدعاء تلك النقطة النهائية مباشرة (أو تفحص الاستجابات في أدوات المطور). التفويض الحقيقي يجب أن يحدث على الخادم أيضاً.

الهدف الجيد هو تغطية الجانبَين: حظر الصفحات وحظر البيانات. إذا فتح وكيل دعم مسارًا خاصًا بالمسؤول فقط، يجب أن يمنع الحارس التنقل ويعرض "تم رفض الوصول". وبشكل منفصل، يجب على الواجهة الخلفية رفض نداءات API الخاصة بالمسؤولين فقط، حتى لا يتم إرجاع بيانات مقيدة.

اختر نموذج أدوار وصلاحيات بسيط

يتعقد التحكم في الوصول عندما تبدأ بقائمة طويلة من الأدوار. ابدأ بمجموعة صغيرة يفهمها الناس فعلاً، ثم أضف صلاحيات أدق فقط عندما تشعر بألم حقيقي.

تقسيم عملي هو:

  • الأدوار تصف من هو الشخص في تطبيقك.
  • الصلاحيات تصف ما يمكنه فعله.

بالنسبة لمعظم الأدوات الداخلية، ثلاثة أدوار تغطي الكثير:

  • admin: إدارة المستخدمين والإعدادات، رؤية كل البيانات
  • support: التعامل مع سجلات العملاء والردود، لكن ليس إعدادات النظام
  • viewer: وصول للقراءة فقط إلى الشاشات المصرح بها

قرر مبكراً من أين تأتي الأدوار. مطالبات التوكن (JWT) سريعة للحراس لكنها قد تصبح قديمة حتى يتم تحديثها. جلب ملف تعريف المستخدم عند بدء التطبيق دائمًا ما يكون حديثاً، لكن يجب أن تنتظر الحراس حتى ينتهي ذلك الطلب.

افصل أيضاً أنواع المسارات بوضوح: مسارات عامة (مفتوحة للجميع)، مسارات تتطلب جلسة (authenticated)، ومسارات مقيدة (تتطلب دورًا أو صلاحية).

عرّف قواعد الوصول باستخدام meta في المسار

أوضح طريقة للتعبير عن الوصول هي إعلانها على المسار نفسه. يسمح لك Vue Router بإرفاق كائن meta لكل سجل مسار حتى يتمكن الحراس من قراءته لاحقاً. هذا يبقي القواعد قريبة من الصفحات التي تحميها.

اختر شكل meta بسيط والتزم به عبر التطبيق.

const routes = [
  {
    path: "/admin",
    component: () =\u003e import("@/pages/AdminLayout.vue"),
    meta: { requiresAuth: true, roles: ["admin"] },
    children: [
      {
        path: "users",
        component: () =\u003e import("@/pages/AdminUsers.vue"),
        // inherits requiresAuth + roles from parent
      },
      {
        path: "audit",
        component: () =\u003e import("@/pages/AdminAudit.vue"),
        meta: { permissions: ["audit:read"] },
      },
    ],
  },
  {
    path: "/tickets",
    component: () =\u003e import("@/pages/Tickets.vue"),
    meta: { requiresAuth: true, permissions: ["tickets:read"], readOnly: true },
  },
]

بالنسبة للمسارات المتداخلة، قرر كيف تُدمَج القواعد. في معظم التطبيقات، يجب أن ترث الأطفال متطلبات الأب. في حارسك، افحص كل سجل مسار مطابق (وليس فقط to.meta) حتى لا تُهمل متطلبات الأب.

تفصيل واحد يوفر الوقت لاحقاً: ميز بين "يمكن العرض" و"يمكن التحرير". قد تكون الصفحة مرئية للـ support و admin، لكن يجب تعطيل التحرير للدعم. علامة readOnly: true في meta يمكن أن تُوجّه سلوك الواجهة (تعطيل إجراءات، إخفاء أزرار تدميرية) دون التظاهر بأنها أمان.

جهّز حالة المصادقة لكي تعمل الحراس بأمان

معظم أخطاء الحراس تأتي من مشكلة واحدة: يعمل الحارس قبل أن يعرف التطبيق من هو المستخدم.

عامل المصادقة مثل آلة حالات صغيرة واجعلها مصدر الحقيقة الوحيد. تريد ثلاث حالات واضحة:

  • unknown: التطبيق بدأ للتو، لم يتم التحقق من الجلسة بعد
  • logged out: فحص الجلسة انتهى، لا يوجد مستخدم صالح
  • logged in: تم تحميل المستخدم، الأدوار/الصلاحيات متاحة

القاعدة: لا تقرأ الأدوار بينما المصادقة هي unknown. هذا هو سبب ظهور لمحات من الشاشات المحمية أو إعادة توجيهات مفاجئة إلى تسجيل الدخول.

قرر كيف يعمل تحديث الجلسة

اختر استراتيجية تحديث واحدة وحافظ على توقعها (مثلاً: قراءة توكن، استدعاء نقطة نهاية "من أنا"، تعيين المستخدم).

نمط مستقر يبدو هكذا:

  • عند تحميل التطبيق، ضع auth في حالة unknown وابدأ طلب تحديث واحد
  • حل الحراس فقط بعد انتهاء التحديث (أو انتهاء المهلة)
  • خزّن المستخدم في الذاكرة، لا في route meta
  • عند الفشل، ضع auth في حالة logged out
  • اكشف عن وعد ready (أو ما شابه) يمكن للحراس الانتظار عليه

بمجرد وجود هذا، تبقى منطق الحارس بسيطاً: انتظر حتى تصبح auth جاهزة، ثم قرر الوصول.

خطوة بخطوة: تنفيذ التفويض على مستوى المسار

أعد تسجيل الدخول بالطريقة الصحيحة
Use AppMaster auth modules to manage sessions and user profiles cleanly.
إعداد المصادقة

نهج نظيف هو إبقاء معظم القواعد في حارس عام واحد، واستخدام حراس لكل مسار فقط عندما يحتاج المسار فعلاً إلى منطق خاص.

1) أضف حارس beforeEach عام

// router/index.js
router.beforeEach(async (to) =\u003e {
  const auth = useAuthStore()

  // Step 2: wait for auth initialization when needed
  if (!auth.ready) await auth.init()

  // Step 3: check authentication, then roles/permissions
  if (to.meta.requiresAuth \u0026\u0026 !auth.isAuthenticated) {
    return { name: 'login', query: { redirect: to.fullPath } }
  }

  const roles = to.meta.roles
  if (roles \u0026\u0026 roles.length \u003e 0 \u0026\u0026 !roles.includes(auth.userRole)) {
    return { name: 'forbidden' } // 403
  }

  // Step 4: allow navigation
  return true
})

هذا يغطي معظم الحالات دون نشر الفحوصات عبر المكونات.

متى يكون beforeEnter الأنسب

استخدم beforeEnter عندما تكون القاعدة خاصة فعلاً بالمسار، مثل "فقط صاحب التذكرة يمكنه فتح هذه الصفحة" وتعتمد على to.params.id. اجعلها قصيرة وأعد استخدام نفس مخزن المصادقة حتى يبقى السلوك متسقاً.

إعادة توجيهات آمنة دون فتح ثغرات

أطلق أداة داخلية
Create admin panels and support dashboards with controlled access in AppMaster.
بناء الأداة

يمكن أن تقوّض عمليات إعادة التوجيه ضوابط الوصول بهدوء إذا عاملتها كمُدخل موثوق.

النمط الشائع هو: عندما يكون المستخدم غير مسجل الدخول، أرسله إلى تسجيل الدخول وضع استعلام returnTo. بعد تسجيل الدخول، اقرأه وتنقل هناك. الخطر هو إعادة التوجيه المفتوحة (إرسال المستخدمين إلى مكان غير مقصود) والحلقات.

حافظ على سلوك بسيط:

  • المستخدمون غير المسجلين يذهبون إلى Login مع returnTo مضبوط على المسار الحالي.
  • المستخدمون المسجلون لكن غير المصرح لهم يذهبون إلى صفحة Forbidden مخصصة (وليس Login).
  • فقط اسمح بقيم returnTo داخلية تعرفها.
  • أضف فحص حلقة واحد حتى لا تعيد التوجيه إلى نفس المكان.
const allowedReturnTo = (to) =\u003e {
  if (!to || typeof to !== 'string') return null
  if (!to.startsWith('/')) return null
  // optional: only allow known prefixes
  if (!['/app', '/admin', '/tickets'].some(p =\u003e to.startsWith(p))) return null
  return to
}

router.beforeEach((to) =\u003e {
  if (!auth.isReady) return false

  if (!auth.isLoggedIn \u0026\u0026 to.name !== 'Login') {
    return { name: 'Login', query: { returnTo: to.fullPath } }
  }

  if (auth.isLoggedIn \u0026\u0026 !canAccess(to, auth.user) \u0026\u0026 to.name !== 'Forbidden') {
    return { name: 'Forbidden' }
  }
})

تجنب تسريب بيانات مقيدة أثناء التنقل

أسهل تسريب هو تحميل البيانات قبل أن تعرف ما إذا كان المستخدم مسموحًا له برؤيتها.

في Vue، يحدث هذا غالبًا عندما تجلب الصفحة بيانات في setup() ويعمل حارس الراوتر بعد لحظة. حتى لو تم إعادة توجيه المستخدم، قد تصل الاستجابة إلى مخزن مشترك أو تومض على الشاشة.

قاعدة أكثر أمانًا: فوض أولاً، ثم احمِ البيانات.

// router guard: authorize before entering the route
router.beforeEach(async (to) =\u003e {
  await auth.ready() // ensure roles are known
  const required = to.meta.requiredRole
  if (required \u0026\u0026 !auth.hasRole(required)) {
    return { name: 'forbidden' }
  }
})

راقب أيضاً الطلبات المتأخرة عندما يتغير التنقل بسرعة. ألغِ الطلبات (مثلاً باستخدام AbortController) أو تجاهل الاستجابات المتأخرة بفحص معرف الطلب.

التخزين المؤقت (caching) فخ آخر شائع. إذا خزّنت "آخر سجل عميل مُحمّل" عالمياً، فقد تُعرض استجابة خاصة بالمشرف لاحقًا لمستخدم غير مشرف يزور نفس هيكل الشاشة. قم بتمييز الكاش حسب معرف المستخدم والدور، وامسح الوحدات الحساسة عند تسجيل الخروج (أو عند تغيير الأدوار).

بعض العادات تمنع معظم التسريبات:

  • لا تجلب بيانات حساسة حتى يؤكد التفويض.
  • مفتاح البيانات المخزنة ذاياً بالمستخدم والدور، أو احتفظ بها محلياً في الصفحة.
  • ألغِ أو تجاهل الطلبات الجارية عند تغيير المسار.

بدائل ودية: 401 و403 و404

ربط الخدمات الأساسية بسرعة
Add Stripe billing and Telegram or email notifications with built-in integrations.
أضف التكاملات

مسارات الـ "لا" لا تقل أهمية عن مسارات الـ "نعم". صفحات البدائل الجيدة تبقي المستخدمين موجهين وتقلل طلبات الدعم.

401: تسجيل الدخول مطلوب (غير مصدق)

استخدم 401 عندما لا يكون المستخدم مسجلاً. اجعل الرسالة بسيطة: يحتاج لتسجيل الدخول للمتابعة. إذا تدعم العودة إلى الصفحة الأصلية بعد تسجيل الدخول، فتأكد من التحقق من مسار العودة حتى لا يشير خارج تطبيقك.

403: مرفوض الوصول (مصدق لكن غير مصرح)

استخدم 403 عندما يكون المستخدم مسجلاً لكنه يفتقر للصلاحية. اجعل الرسالة محايدة وتجنب تلميح تفاصيل حساسة.

صفحة 403 جيدة عادةً تحتوي على عنوان واضح ("تم رفض الوصول"), جملة شرح واحدة، وخطوة آمنة تالية (العودة إلى لوحة التحكم، الاتصال بمشرف، أو تغيير الحساب إن وُجد).

404: غير موجود

تعامل مع 404 بشكل منفصل عن 401/403. وإلا سيفترض الناس أنهم يفتقرون إلى الأذن بينما الصفحة ببساطة غير موجودة.

أخطاء شائعة تكسر ضوابط الوصول

معظم أخطاء التحكم في الوصول هي أخطاء منطق بسيطة تظهر كحلقات إعادة توجيه، لمحات من الصفحة الخاطئة، أو وقف المستخدمين.

المذنبات المعتادة:

  • اعتبار UI المخفي كـ"أمان". نفِّذ دائمًا الأدوار في الراوتر وعلى الـ API.
  • قراءة الأدوار من حالة قديمة بعد تسجيل الخروج/الدخول.
  • إعادة توجيه المستخدمين غير المصرح لهم إلى مسار محمي آخر (حلقة فورية).
  • تجاهل لحظة "المصادقة لا تزال جارِ تحميلها" عند التحديث.
  • الخلط بين 401 و403، مما يربك المستخدمين.

مثال واقعي: وكيل دعم يقوم بتسجيل الخروج ومسؤول يسجل الدخول على نفس الحاسوب المشترك. إذا قرأ الحارس دورًا مخزنًا مؤقتًا قبل تأكيد الجلسة الجديدة، يمكنك حظر المسؤول بطريق الخطأ أو، والأسوأ، السماح بالوصول لفترة وجيزة لا يجب أن يسمح بها.

قائمة فحص سريعة قبل الإطلاق

أضف تفويض حقيقي للواجهة الخلفية
Design APIs and business rules in AppMaster so data is protected, not just routes.
إنشاء الواجهة الخلفية

قم بمرور قصير يركز على اللحظات التي عادةً ما تنهار فيها ضوابط الوصول: الشبكات البطيئة، الجلسات منتهية الصلاحية، وعناوين URL المحفوظة.

  • لكل مسار محمي يوجد متطلبات meta صريحة.
  • الحراس يتعاملون مع حالة تحميل المصادقة دون إظهار واجهات محمية مؤقتة.
  • المستخدمون غير المصرح لهم يصلون إلى صفحة 403 واضحة (وليس ارتداد محير إلى الصفحة الرئيسية).
  • أي إعادة توجيه "العودة إلى" تم التحقق منها ولا يمكنها خلق حلقات.
  • نداءات API الحساسة تعمل فقط بعد تأكيد التفويض.

ثم اختبر سيناريو واحد من البداية للنهاية: افتح عنوان URL محمي في تبويب جديد أثناء تسجيل الخروج، سجل الدخول كمستخدم عادي، وتأكد إما أن تصل إلى الصفحة المقصودة (إن كانت مصرح بها) أو إلى 403 نظيفة مع خطوة تالية.

مثال: وصول الدعم مقابل المشرف في تطبيق ويب صغير

أنشئ صفحات بديلة ودية
Build 401, 403, and 404 pages fast with AppMaster UI builders.
بناء الواجهة

تخيل تطبيق دعم فني بدورين: support و admin. يمكن للدعم قراءة والرد على التذاكر. المشرف يمكنه ذلك أيضاً، بالإضافة إلى إدارة الفوترة وإعدادات الشركة.

  • /tickets/:id مسموح لـ support و admin
  • /settings/billing مسموح فقط لـ admin

لحظة شائعة: يفتح وكيل دعم رابطًا عميقًا إلى /settings/billing من إشارة مرجعية قديمة. يجب على الحارس فحص meta قبل تحميل الصفحة وحظر التنقل. لأن المستخدم مسجل ولكن يفتقر للدور، يجب أن يصل إلى بديل آمن (403).

رسالتان مهمتان:

  • تسجيل الدخول مطلوب (401): «يرجى تسجيل الدخول للمتابعة.»
  • تم رفض الوصول (403): «ليس لديك صلاحية الوصول إلى إعدادات الفوترة.»

ما يجب ألا يحدث: مكون الفوترة يركب، أو تُجلب بيانات الفوترة، ولو لحظة وجيزة.

تغيير الدور في منتصف الجلسة هو حالة حافة أخرى. إذا تمت ترقية شخص أو خفضه، لا تعتمد على القائمة. أعد فحص الأدوار عند التنقل وقرر كيف ستتعامل مع الصفحات النشطة: حدّث حالة المصادقة عندما يتغير الملف الشخصي، أو اكتشف تغيّر الأدوار وأعِد التوجيه بعيدًا عن الصفحات التي لم تعد مسموحًا بها.

الخطوات التالية: حافظ على قواعد الوصول قابلة للصيانة

بمجرد أن تعمل الحراس، الخطر الأكبر هو الانجراف: مسار جديد يُنشر بدون meta، دور يُعاد تسميته، وتصبح القواعد غير متسقة.

حوّل قواعدك إلى خطة اختبار صغيرة يمكنك تشغيلها عند إضافة مسار:

  • كزائر: افتح المسارات المحمية وتأكد من وصولك إلى تسجيل الدخول دون رؤية محتوى جزئي.
  • كمستخدم: افتح صفحة لا يجب أن تصل إليها وتأكد من حصولك على 403 واضحة.
  • كمشرف: جرب الروابط العميقة المنسوخة من شريط العنوان.
  • لكل دور: حدث الصفحة على مسار محمي وتأكد من استقرار النتيجة.

إذا أردت طبقة أمان إضافية، أضف عرضًا اختباريًا في بيئة التطوير أو إخراجًا في وحدة التحكم يسرد المسارات ومتطلبات meta الخاصة بها، حتى تبرز القواعد المفقودة فوراً.

إذا كنت تبني أدوات داخلية أو بوابات باستخدام AppMaster (appmaster.io)، يمكنك تطبيق نفس النهج: اجعل حراس المسار مركّزة على التنقل في واجهة Vue3، ونفّذ الصلاحيات حيث تعيش منطق البيانات والواجهة الخلفية.

اختر تحسناً واحداً وطبّقه من البداية للنهاية: تشديد بوابات جلب البيانات، تحسين صفحة 403، أو تشديد منطق إعادة التوجيه. الإصلاحات الصغيرة هي التي توقف معظم أخطاء التحكم في العالم الحقيقي.

الأسئلة الشائعة

هل حراس المسار أمان فعلي أم مجرد تجربة للمستخدم؟

Route guards control navigation, not data access. They help you block a page, redirect, and show a clean 401/403 state, but they cannot stop someone from calling your API directly. Always enforce the same permissions on the backend so restricted data is never returned.

لماذا إخفاء عنصر في القائمة لا يكفي للوصول حسب الدور؟

Because hiding UI only changes what someone sees, not what they can request. Users can still type a URL, open bookmarks, or hit deep links. You need router checks to block the page, and server-side authorization to block the data.

ما نموذج الأدوار والصلاحيات البسيط الذي أبدأ به؟

Start with a small set that people understand, then add permissions when you feel real pain. A common baseline is admin, support, and viewer, then add permissions like tickets:read or audit:read for specific actions. Keep “who you are” (role) separate from “what you can do” (permission).

كيف أستخدم `meta` في Vue Router للتحكم في الوصول؟

Put access rules in meta on the route records, like requiresAuth, roles, and permissions. This keeps rules next to the pages they protect and makes your global guard predictable. For nested routes, check every matched record so parent requirements aren’t skipped.

كيف أتعامل مع المسارات المتداخلة بحيث يرث الأطفال قيود الآباء؟

Read from to.matched and combine requirements across all matched route records. That way, a child route can’t accidentally bypass a parent’s requiresAuth or roles. Decide a clear merge rule up front (usually: parent requirements apply to children).

كيف أوقف حلقات إعادة التوجيه وظهور صفحات محمية عند التحديث؟

Because the guard may run before the app knows who the user is. Treat auth as three states—unknown, logged out, logged in—and never evaluate roles while auth is unknown. Make guards wait for one initialization step (like a single “who am I” request) before deciding.

متى أستخدم global `beforeEach` مقابل `beforeEnter`؟

Default to a global beforeEach for consistent rules like “requires login” and “requires role/permission.” Use beforeEnter only when the rule is truly route-specific and depends on params, like “only the ticket owner can open this page.” Keep both paths using the same auth source of truth.

كيف أتعامل مع إعادة التوجيه بعد تسجيل الدخول دون فتح ثغرات لإعادة توجيه خارجية؟

Treat returnTo as untrusted input. Only allow internal paths you recognize (for example, values that start with / and match known prefixes), and add one loop check so you don’t redirect back to the same blocked route. Logged-out users go to Login; logged-in but unauthorized users go to a dedicated 403 page.

كيف أتجنب تسريب بيانات مقيدة أثناء التنقل؟

Authorize before fetching. If a page fetches data in setup() and you redirect a moment later, the response can still land in a store or briefly show. Gate sensitive requests behind confirmed authorization, and cancel or ignore in-flight requests on navigation changes.

ما الفرق الصحيح بين 401 و403 و404 في تطبيق Vue؟

Use 401 when the user is not signed in, and 403 when they are signed in but not allowed. Keep 404 separate so users don’t think they lack permission for a route that simply doesn’t exist. Clear, consistent fallbacks reduce confusion and support tickets.

من السهل أن تبدأ
أنشئ شيئًا رائعًا

تجربة مع AppMaster مع خطة مجانية.
عندما تكون جاهزًا ، يمكنك اختيار الاشتراك المناسب.

البدء