إنتقل إلى المحتوى الرئيسي

المصادقة والأمان

يستخدم Libre WebUI حسابات مستخدمين محلية مع جلسات JWT. ويسمح التثبيت الجديد دائمًا بإنشاء مسؤول محلي أول. أما التسجيل العام لكل حساب محلي أو OAuth تالٍ فمغلق افتراضيًا.

الإعداد لأول مرة

عندما لا تحتوي قاعدة البيانات مستخدمين:

  1. يعرض Libre WebUI مسار الإعداد الأولي.
  2. ينشئ المستخدم أول حساب محلي.
  3. يُسند إلى الحساب دور admin.
  4. يظل كل تسجيل عام لاحق مغلقًا ما لم يُفعّل صراحة.

تحتفظ قواعد البيانات القائمة بمستخدميها وأدوارهم الحالية.

الحسابات المحلية

يتطلب التسجيل المحلي:

  • اسم مستخدم
  • كلمة مرور بين 12 حرفًا و72 بايت UTF-8، تتضمن حرفًا كبيرًا وحرفًا صغيرًا ورقمًا
  • بريدًا إلكترونيًا اختياريًا

تُجزأ كلمات المرور باستخدام bcrypt قبل التخزين. وتخضع مسارات الدخول والتسجيل لتحديد المعدل.

اعتماد التسجيل

لا يمنح التسجيل العام الوصول وحده. يبدأ كل حساب أُنشئ عبر استمارة التسجيل العامة أو مزوّد OAuth في حالة pending، ويجب أن يعتمده مسؤول قبل أن يسجل الدخول.

الاستثناء الوحيد هو التمهيد: يُنشأ أول حساب حقيقي في قاعدة فارغة بحالة active ودور admin ضمن عملية ذرية، ليظل التثبيت الجديد قادرًا على إنشاء مسؤول يعمل. وكل تسجيل لاحق ينتظر المراجعة.

ما يراه المستخدم المعلق:

  • ينجح التسجيل، لكنه لا يعيد رمز جلسة. تستجيب API برمز 202 مع approvalRequired: true، وتوضح الواجهة أن على مسؤول اعتماد الحساب.
  • يُرفض الدخول بكلمة مرور صحيحة برمز 403 والشيفرة ACCOUNT_PENDING ("Your account is waiting for administrator approval"). ويعيد OAuth التوجيه إلى صفحة الدخول مع ?approval=pending.
  • تُقرأ حالة الحساب من قاعدة البيانات في كل طلب موثق، فلا يمكن أن تتجاوز جلسة حالة الحساب active.

ما يراه المسؤول:

  • تعرض إدارة المستخدمين بطاقة اعتمادات معلقة تسرد الحسابات المنتظرة، مع إجراء تنشيط الحساب وإجراء رفض لكل منها. الرفض حذف؛ ولا توجد حالة تعليق مستقلة.
  • يتلقى المسؤولون إشعارًا داخل التطبيق أثناء الدخول: شارة على عنصر المستخدمين وتنبيه عند وصول تسجيلات جديدة. ويُستطلع ملخص الاعتمادات مرة كل دقيقة تقريبًا (GET /api/users/pending-approvals، للمسؤولين فقط).
  • يسجل الاعتماد (PATCH /api/users/:id/approve، للمسؤولين فقط) المسؤول الذي وافق ووقت الموافقة. ولا يغير الدور؛ تبقى الحسابات بدور user حتى يرقّيها مسؤول. يسري الاعتماد في محاولة الدخول التالية، ولا حاجة إلى إعادة إنشاء شيء.

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

تفعيل التسجيل العام عمدًا

التسجيل معطل افتراضيًا. اضبط متغير الخادم الخلفي التالي فقط خلال الفترة التي تريد فيها قبول حسابات محلية أو OAuth جديدة:

ENABLE_SIGNUP=true

أعده إلى false بعد نافذة التسجيل المخططة. يظل المستخدمون المحليون وOAuth القائمون قادرين على الدخول، ويستطيع المسؤولون إنشاء حسابات من إدارة المستخدمين مع إغلاق التسجيل العام.

تسمح قاعدة فارغة دائمًا بمسؤول محلي واحد حتى مع ENABLE_SIGNUP=false؛ ولا يستطيع OAuth شغل خانة التمهيد. لنشر بعيد خاص، ضع اسم المضيف خلف قائمة هويات مسموحة مثل Cloudflare Access قبل تشغيل التطبيق، ثم أنشئ المسؤول الأول عبر ذلك المسار المحمي.

الأدوار

الدورالغرض
adminإدارة المثيل والمستخدمين وإعدادات النظام وتشغيل بيئة Work الموثوقة
userمسارات المحادثة والنماذج والشخصيات والمستندات والإعدادات العادية

يقتصر تثبيت النماذج وحذفها ونسخها ودفعها وإلغاء تحميلها على المسؤولين لأنها تغير موارد المضيف.

الوصول إلى Work

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

يُفحص تصريح المسؤول وفق الدور الحالي في قاعدة البيانات، لا الدور المخزن في JWT فقط. ولذلك تلغي خفض رتبة المسؤول وصوله إلى Work فورًا. ثم يحاول الخادم إجهاض التشغيلات النشطة وإيقاف حاويات المستخدم ومعايناته، مع الاحتفاظ بسجلات المهام والوحدات المسماة. وإذا فشل تنظيف Docker يبقى الوصول ملغى ويبلغ تغيير الدور عن الفشل، وعلى المشغّل استعادة الوصول إلى Docker وإعادة محاولة التنظيف.

حذف المستخدم مدمر لبيانات Work الخاصة به. يوقف Libre WebUI حاوياته المُدارة ويحذف وحداته أولًا، ثم يحذف الحساب وسجلات قاعدة البيانات. وإذا تعذر على Docker إثبات نجاح التنظيف، يفشل الحذف ليصحح المسؤول مشكلة البيئة ويعيد المحاولة.

المجموعات ومنح الموارد

ينشئ المسؤولون المجموعات ويديرون عضويتها من تبويب إدارة المستخدمين في الإعدادات. المجموعات جهات رئيسية لمنح الموارد: يستطيع مالك محادثة أو ملاحظة أو مستند أو مجموعة معرفة أو مجلد أو شخصية أو مطالبة أو مهارة أو تقويم منح read أو write أو admin لمستخدم أو مجموعة عبر API الوصول. تستخدم كل الأسطح القابلة للمشاركة مربع الحوار نفسه (راجع المشاركة)، ويستطيع المسؤولون تقييد خوادم الأدوات بالطريقة نفسها. تظل الموارد خاصة افتراضيًا؛ فلا يمنح دور admin العام وصولًا إلى محتوى الآخرين. تُقيّم العضوية وقت الطلب، فيُلغي إزالة عضو وصول المجموعة فورًا. وتجيب شاشة «الوصول الفعلي» في تبويب إدارة المستخدمين بالإعدادات عن سبب قدرة المستخدم على الوصول عبر سرد دوره ومجموعاته وميزات وصوله وكل المنح التي تصله.

سجل تدقيق الأمان

تُسجل الإجراءات الحساسة — تسجيلات الدخول وفشلها والخروج وإلغاء الجلسات والرموز وتغييرات المستخدمين والمجموعات والمنح والرموز — في سجل تدقيق للإضافة فقط منفصل عن تحليلات الاستخدام. وتُنقح التفاصيل قبل التخزين؛ تُحذف المفاتيح الشبيهة بالأسرار وتُحدد أحجام الحمولات، فلا تدخل كلمات المرور أو الرموز أو محتوى المطالبات السجل. وتكتب تغييرات المجموعات والمنح حدث التدقيق في معاملة قاعدة البيانات نفسها، فلا يوجد تغيير بلا أثر. يستطيع المسؤولون الاستعلام من تبويب إدارة المستخدمين في الإعدادات؛ ومدة الاحتفاظ الافتراضية 180 يومًا (AUDIT_RETENTION_DAYS).

الجلسات

يوقّع الخادم JWT باستخدام JWT_SECRET. اضبط سرًا ثابتًا في الإنتاج:

JWT_SECRET=replace-with-a-long-random-secret

يؤدي تغيير JWT_SECRET إلى إبطال الجلسات القائمة. تستخدم رموز الدخول المحلية وOAuth قيمة JWT_EXPIRES_IN، وافتراضيها 7d؛ ويؤثر تغييرها في الجلسات الجديدة. تستبدل اتصالات WebSocket الرمز الدائم بتذكرة قصيرة العمر تُستخدم مرة واحدة، وتغلق عند انتهاء الجلسة الأساسية.

ينشئ كل دخول أيضًا سجل جلسة على الخادم مرتبطًا بـ JWT. تسرد الإعدادات ← الجلسات كل جهاز مع طريقة الدخول وأول نشاط وآخر نشاط والانتهاء. يؤدي إلغاء جلسة هناك (أو «تسجيل خروج الجلسات الأخرى») إلى إبطال رمزها فورًا على كل نسخة وإغلاق اتصالات WebSocket الحية؛ ويلغي الخروج الجلسة الحالية بالطريقة نفسها. الرموز الصادرة قبل هذه الميزة بلا معرف جلسة وتظل صالحة حتى الانتهاء، إلا أن إجراء «خروج الجلسات الأخرى» من دخول جديد يطبع أيضًا حدًا زمنيًا للحساب يرفضها.

المصادقة الثنائية ومفاتيح المرور

تدير الإعدادات ← الجلسات العوامل الثانية والدخول بلا كلمة مرور:

  • تطبيق المصادقة (TOTP). يعرض التسجيل سر base32 ورابط otpauth:// لأي تطبيق؛ يؤكد أول رمز من 6 أرقام التفعيل ويكشف عشرة رموز استرداد لمرة واحدة. بعد ذلك يعيد دخول كلمة المرور تحديًا قصيرًا بدل جلسة، ويكمل POST /api/auth/mfa/verify الدخول برمز TOTP أو استرداد. يُسجل الإطار الزمني لكل رمز مقبول لمنع إعادة استخدام رمز معترض؛ ولا تُخزن رموز الاسترداد إلا كرموز بحث أحادية الاتجاه بمفتاح، ويعمل كل منها مرة واحدة. يتطلب التعطيل أو تجديد الرموز إثبات عامل من جديد.
  • مفاتيح المرور (WebAuthn). ينفذ «الدخول بمفتاح مرور» دخولًا بلا كلمة مرور ببيان اعتماد قابل للاكتشاف؛ ويلزم تحقق المستخدم (قفل الشاشة أو المقاييس الحيوية أو PIN) عند التسجيل والدخول. يُقبل الإثبات كـ none، وتُدعم بيانات ES256 وEdDSA، وتُشفّر المادة أثناء التخزين مع حفظ المعرف كرمز بحث بمفتاح. التحديات لمرة واحدة وتنتهي بعد خمس دقائق؛ ويُرفض عداد توقيع غير صفري لا يتقدم كإشارة نسخ. تحتاج مفاتيح المرور أصلًا آمنًا (HTTPS) أو localhost في التطوير؛ اضبط WEBAUTHN_RP_ID إذا وصل المثيل عبر أكثر من اسم مضيف.

يُوقّع رمز تحدي MFA بعد كلمة مرور صحيحة بسر مشتق من JWT_SECRET لكنه مختلف عنه؛ فلا يمكنه مصادقة طلب API، وهو مربوط بحساب وغرض واحد ويُستهلك عند النجاح.

يستطيع المسؤولون فرض عامل ثانٍ على كل حساب (المستخدمون ← بطاقة سياسة العاملين، أو تثبيته بـ MFA_REQUIRED_MODE=required). ويُوجّه من لا يملكه إلى التسجيل في دخوله التالي قبل إصدار الجلسة. يستطيع المسؤول أيضًا إعادة ضبط تسجيل TOTP لاسترداد الحساب؛ وتبقى مفاتيح المرور لأن المستخدم يديرها من الإعدادات. ويُسجل التسجيل والتفعيل وفشل التحقق والتعطيل وتغيير السياسة وتسجيل/إزالة مفاتيح المرور وإعادة ضبط المسؤول في سجل الأمان.

تنطبق MFA على دخول كلمة المرور. وتعتمد عمليات OAuth وOIDC على العامل الثاني لمزوّد الهوية ولا تُتحدى ثانية. ولا تتأثر رموز API؛ فهي لا تستخدم مصادقة الجلسة.

رموز API

تنشئ الإعدادات ← مفاتيح API رموز وصول شخصية (بادئة lwk_) للاستخدام البرمجي. يظهر السر مرة ويُخزن كتجزئة فقط. يحمل كل رمز قائمة نطاقات صريحة (chat وmodels وdocuments وnotes وpersonas وmedia وwork وadmin)؛ ويربط الخادم كل عائلة مسارات بنطاق مطلوب، فلا يستطيع رمز للملاحظات لمس المحادثات أو الإدارة، ولا يمكن إدارة الجلسات بالرمز. تدعم الرموز انتهاءً اختياريًا وتتبع آخر استخدام ويمكن إلغاؤها وتُحدد بمعدل لكل رمز عبر النسخ. لا ينشئ رمز admin إلا مسؤول، ويجب أن يظل الحساب مسؤولًا عند استخدامه. كما أن رمز chat هو مفتاح API العام /v1 المتوافق مع OpenAI.

Cloudflare Turnstile

يحمي Turnstile الدخول بكلمة المرور والتسجيل عند تهيئة المفتاحين:

TURNSTILE_SITE_KEY=...
TURNSTILE_SECRET_KEY=...
TURNSTILE_EXPECTED_HOSTNAME=chat.example.com

تسند الواجهة إجراءي login وsignup منفصلين. يتحقق الخادم من الرمز لدى Cloudflare ويرفض استجابة لا يطابق اسم مضيفها أو إجراءها الطلب. يوفر BASE_URL اسم المضيف المتوقع إذا لم تُضبط TURNSTILE_EXPECTED_HOSTNAME صراحة.

إذا غاب أي مفتاح، يُعطل Turnstile.

OAuth عبر GitHub

هيّئ:

GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
GITHUB_CALLBACK_URL=https://your-domain.example/api/auth/oauth/github/callback

ينشئ مسار GitHub OAuth مستخدمين محليين بأسماء تبدأ بـ gh_ ويسند إليهم دور user افتراضيًا.

OAuth عبر Hugging Face

هيّئ:

HUGGINGFACE_CLIENT_ID=...
HUGGINGFACE_CLIENT_SECRET=...
HUGGINGFACE_CALLBACK_URL=https://your-domain.example/api/auth/oauth/huggingface/callback

ينشئ مسار Hugging Face OAuth مستخدمين محليين بأسماء تبدأ بـ hf_ ويسند إليهم دور user افتراضيًا.

يستخدم المزوّدان قيمة state عشوائية آمنة تشفيريًا مرتبطة بملف تعريف ارتباط HttpOnly وSameSite قصير العمر. ويرفض الاستدعاء حالة مفقودة أو غير مطابقة. وبعد نجاحه، يعبر JWT إلى الواجهة في ملف HttpOnly مدته 60 ثانية يُستبدل ويُمسح فورًا؛ ولا توضع رموز Bearer في عناوين الاستدعاء أو سجل المتصفح أو ترويسات المُحيل.

إعادة التوجيه وCORS

اضبط BASE_URL لقيم الاستدعاء الافتراضية وCORS_ORIGIN لوصول المتصفح:

BASE_URL=https://your-domain.example
CORS_ORIGIN=https://your-domain.example

في التطوير المحلي، أدرج أصل Vite:

CORS_ORIGIN=http://localhost:5173,http://127.0.0.1:5173

الوضع التجريبي

الوضع التجريبي وضع معاينة للواجهة. يملأ بيانات تجريبية معطلة ويستخدم استجابات API وهمية. وليس وضع مصادقة للإنتاج.

قائمة تحقق أمنية

  • اضبط JWT_SECRET قويًا.
  • أبقِ DATA_DIR في تخزين دائم محكوم الوصول.
  • انسخ ENCRYPTION_KEY احتياطيًا مع قاعدة البيانات.
  • هيّئ Turnstile للتسجيل العام.
  • استخدم HTTPS للنشر العام.
  • قيّد مفاتيح API للمزوّدين إلى الحد الأدنى اللازم.
  • اجعل عناوين استدعاء OAuth دقيقة.
  • لا تمنح Work (لحسابات المسؤول أو الوضع المفتوح للجميع) إلا لمن تثق بتشغيله بيئة حاويات الخادم الخلفي.

وثائق ذات صلة