الاستيثاق (Authentification) في Laravel

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

محتويات

مقدمة

تريد أن تبدأ بسرعة؟ فقط شغِّل الأمر php artisan make:auth و php artisan migrate في تطبيق Laravel جديد. ثم انتقل بالمتصفح إلى العنوان http://your-app.test/register أو أي عنوان URL آخر تم تعيينه لتطبيقك. هذان الأمران سوف يعتنيان بنظام الاستيثاق بأكمله الخاص بك!

يجعل Laravel برمجة نظام الاستيثاق بسيطةًجدًا. في الحقيقة، يُعدّ كل شيء تقريبًا بالنسبة لك افتراضيًا دون تدخلٍ منك. يوجد ملف إعدادات الاستيثاق في config/auth.php، والذي يحتوي على العديد من الخيارات الموثقة جيدًا لتغيير وتبديل سلوك خدمات الاستيثاق.

في جوهرها، تتكون مرافق التوثيق من "الحراس - guards" و "الموفرين - providers".

يحدد الحراس كيفية استيثاق المستخدمين عند كل طلب. على سبيل المثال، يأتي Laravel مع الحارس session الذي يحافظ على الحالة باستخدام بتخزين الجلسة وملفات تعريف الارتباط (cookies).

يحدد الموفرون كيفية استرداد معلومات المستخدمين من سعة التخزين الدائم. يأتي Laravel بالدعم لاسترداد معلومات المستخدمين باستخدام Eloquent ومنشئ استعلام قاعدة البيانات. ومع ذلك، أنت حر في تعريف المزيد من موفري الخدمات حسب حاجة تطبيقك.

لا تقلق إذا كان كل هذا يبدو محيرًا الآن! أغلب التطبيقات لا تحتاج للتغيير على إعدادات الاستيثاق التلقائية.

اعتبارات قاعدة البيانات

تلقائيَا، يتضمن Laravel نموذج App\User Eloquent في ملف تطبيقك. يمكن استخدام هذا النموذج مع برنامج التشغيل التلقائي للاستيثاق Eloquent. إذا كان تطبيقك لا يستخدم Eloquent، فيمكنك استخدام برنامج تشغيل الاستيثاق الخاص بقاعدة البيانات والذي يستخدم منشئ الاستعلام (query builder) الخاص بإطار Laravel.

عند إنشاء مخطط قاعدة البيانات لنموذج App\User، تأكد بأن طول عمود كلمة المرور لا يقل عن 60 محرفًا. الخيار الجيد سيكون الحفاظ على الطول التلقائي لعمود السلاسل النصية والذي يكون 255 محرفًا.

عليك أن تتأكد أيضًا من أن جدول المستخدمين users (أو ما يعادله) يحتوي على عمودٍ يقبل سلسلة نصية remembre_token من 100 حرف ويمكن أن تكون قيمته فارغةً (null). سيُستخدَم هذا العمود لتخزين رمز مميز للمستخدمين الذين يختارون (تذكرني - remember me) عند تسجيل الدخول إلى تطبيقك.

مدخل سريع إلى الاستيثاق

يأتي Laravel مع العديد من وحدات تحكم الاستيثاق التي تكون منشأة مسبقًا، والتي تقع في مجال الأسماء App\Http\Controllers\Auth. يعالج RegisterController تسجيلات المستخدمين الجدد، ويتعامل LoginController مع الاستيثاق، يعالج ForgotPasswordController روابط البريد الإلكتروني لإعادة تعيين كلمات المرور، و يحتوي ResetPasswordController على المنطق اللازم لإعادة ضبط كلمات المرور. يستخدم كل من وحدات التحكم المذكورة سمة (trait) لإدراج التوابع الضرورية لها. بالنسبة للكثير من التطبيقات، لن تحتاج إلى تعديل وحدات التحكم هذه على الإطلاق.

التوجيه

يوفر Laravel طريقة سريعة لتجميع جميع المسارات والواجهات التي تحتاج لها للاستيثاق باستخدام أمرٍ واحدٍ بسيطٍ:
php artisan make:auth

يجب استخدام هذا الأمر على التطبيقات الجديدة، حيث سيقوم بتثبيت تخطيط الواجهة (layout view)، وواجهات التسجيل (registration) وتسجيل الدخول (login)، بالإضافة إلى المسارات لكل نقاط النهاية الخاصة بالاستيثاق. سيولَّد HomeController أيضًا للتعامل مع طلبات ما بعد تسجيل الدخول للوحة التحكم الخاصة بتطبيقك.

الواجهات

كما ذكرنا في القسم السابق، فإن الأمر php artisan make:auth سيُنشِئ كل الواجهات التي تحتاج ها للاستيثاق ويضعها في المجلد resources/views/auth.

الأمر make:auth سيُنشِئ أيضًا المجلد resources/views/layouts الذي يحتوي على التخطيط الأساسي (base layout) الخاص بتطبيقك. كل هذه الواجهات تستخدم إطار العمل Bootstrap، لكنك حر في تخصيصها كيفما تشاء.

الاستيثاق

الآن بعد أن أعددتَ المسارات والواجهات لوحدات تحكم الاستيثاق، أنت جاهز للتسجيل، وللاستيثاق على المستخدمين الجدد لتطبيقك! يمكنك تسجيل الدخول لتطبيقك عن طريق المتصفح لمّا كانت وحدات تحكم الاستيثاق تحتوي على المنطق (عن طريق السمات [traits]) لاستيثاق المستخدمين المسجلين ولتخزين المستخدمين الجدد في قاعدة البيانات.

تخصيص المسار

عندما يتم الاستيثاق على مستخدم بنجاح، سيُعاد توجيهه إلى الرابط/home. يمكنك تخصيص مسار إعادة التوجيه بعد الاستيثاق عن طريق تعريف الخاصية redirectTo على LoginController و RegisterController و ResetPasswordController:
protected $redirectTo = '/';

بعد ذلك، يجب عليك تعديل التابع handle المتحكم بالبرنامج الوسيط RedirectIfAuthenticated لاستخدام رابط URI الجديد الخاص بك عند إعادة توجيه المستخدم.

إذا كان مسار إعادة التوجيه يحتاج إلى منطق إنشاء مخصص، فيمكنك تعريف التابع redirectTo بدلًا من خاصية redirectTo:
protected function redirectTo()

{

   return '/path';

}

ملاحظة: سيكون للتابع redirectTo الأولوية على خاصية redirectTo.

تخصيص اسم المستخدم

بشكل افتراضي، يستخدم Laravel حقل البريد الإلكتروني للاستيثاق. إذا كنت ترغب في تخصيص هذا، فيمكنك تعريف التابع username في LoginController:
public function username()

{

   return 'username';

}

تخصيص الحارس

يمكنك أيضًا تخصيص "الحارس" المستخدم لاستيثاق المستخدمين وتسجيلهم. للبدء، عرّف التابع guard على LoginController، و RegisterController، و ResetPasswordController. يجب أن يعيد التابع نسخة عن الحارس:
use Illuminate\Support\Facades\Auth;

protected function guard()

{

   return Auth::guard('guard-name');

}

التحقق/تخصيص التخزين

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

يحتوي التابع validator في RegisterController على قواعد التحقق من صحة المستخدمين الجدد للتطبيق. أنت حر في تعديل هذا التابع كما تريد.

يُعدّ التابع create في RegisterController مسؤولًا عن إنشاء سجلات App\User جديدة في قاعدة البيانات الخاصة بك باستخدام Eloquent ORM. أنت حر في تعديل هذا التابع وفقًا لاحتياجات قاعدة البيانات الخاصة بك.

استرداد المستخدم المستوثق منه

يمكنك الوصول إلى المستخدم الذي تم استيثاقه عبر واجهة Auth:
use Illuminate\Support\Facades\Auth;

// احصل على المستخدم الحالي المستوثق منه ...
$user = Auth::user();

// احصل على معرف المستخدم الحالي المستوثق منه ID...
$id = Auth::id();
بدلًا من ذلك، بمجرد استيثاق المستخدم، يمكنك الوصول إلى المستخدم الذي تمت الاستيثاق منع عبر نسخة من Illuminate\Http\Request. تذكر أنَّه ستُضاف أصناف type-hinted تلقائيًا في دوال وحدة التحكم الخاصة بك:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
   /**
    * تحديث حساب المستخدم.
    *
    * @param  Request $request
    * @return Response
    */

   public function update(Request $request)

   {
      // $request->user() تعيد نسخة عن المستخدم المستوثق منه ...
   }
}

تحديد ما إذا كان المستخدم الحالي مستوثقًا منه

لتحديد ما إذا كان المستخدم قد قام بالفعل بتسجيل الدخول إلى التطبيق الخاص بك، يمكنك استخدام التابع check على واجهة Auth، والتي ستعيد true إذا كان المستخدم مستوثقًا منه:
use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
  // المستخدم قام بتسجيل الدخول...
}

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

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

يمكن استخدام برنامج وسيط للسماح للمستخدمين الذين تم الاستيثاق lkil فقط بالوصول إلى مسار معين. يعتمد Laravel على الوسيط (middleware)‏ auth، الذي يُعرّف في Illuminate\Auth\Middleware\Authenticate. ولمّا كان هذا الوسيط مسجل بالفعل في نواة HTTP، فكل ما عليك فعله هو إرفاق الوسيط بتعريف المسار:
Route::get('profile', function () {
  // فقط المستخدمين المستوثق منهم يمكنهم الدخول...
})->middleware('auth');
بالطبع، إذا كنت تستخدم وحدات تحكم (controllers)، يمكنك استدعاء التابع middleware من الدالة البانية لوحدة التحكم بدلًا من إرفاقها في تعريف المسار مباشرةً:
public function __construct()
{
   $this->middleware('auth');
}

إعادة توجيه المستخدمين غير المستوثق منهم

عندما يكشف الوسيط auth مستخدمًا غير مصرحٍ به، فإنه سيعرض إما رد JSON 401، أو إذا لم يكن الطلبُ طلبَ AJAX، فسيعيد توجيه المستخدم إلى المسار المسمى login.

يمكنك تعديل هذا السلوك بتعريف التابع unauthenticated في ملف app/Exceptions/Handler.php :
use Illuminate\Auth\AuthenticationException;

protected function unauthenticated($request, AuthenticationException $exception)
{
   return $request->expectsJson()
               ? response()->json(['message' => $exception->getMessage()], 401)
               : redirect()->guest(route('login'));
}

تحديد حارس

عند إرفاق الوسيط (middleware) ‏auth بمسار، يمكنك أيضًا تحديد أي حارس يجب استخدامه للاستيثاق من المستخدم. يجب أن يتطابق الحارس المحدد مع أحد المفاتيح الموجودة في مصفوفة الحراس guards الموجودة في ملف الإعدادات auth.php:
public function __construct()
{
   $this->middleware('auth:api');
}

التضييق على تسجيل الدخول

إذا كنت تستخدم الصنف LoginController المضمن مع Laravel، فسوف يتم تضمين سمة (trait)‏ Illuminate\Foundation\Auth\ThrottlesLogins في وحدة التحكم الخاصة بك. افتراضيًا، لن يتمكن المستخدم من تسجيل الدخول لمدة دقيقة واحدة إذا فشل في تقديم بيانات الاعتماد الصحيحة بعد عدة محاولات. التضييق يكون فردي لاسم المستخدم أو بريده الإلكتروني وعنوان IP الخاص به.

استيثاق المستخدمين يدويًا

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

سنتمكن من الوصول إلى خدمات استيثاق Laravel عبر واجهة Auth ، لذلك سنحتاج إلى التأكد من استيراد واجهة Auth في أعلى الصنف. بعد ذلك، دعنا نتحقق من التابع attempt :
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
   /**
    * التعامل مع كلّ محاولات الاستيثاق     *
    * @param  \Illuminate\Http\Request $request
    *
    * @return Response
    */
   public function authenticate(Request $request)
   {
       $credentials = $request->only('email', 'password');
       if (Auth::attempt($credentials)) {
          // Authentication passed...
           return redirect()->intended('dashboard');
       }
   }
}

يستقبل التابع attempt مصفوفةً من أزواج المفاتيح/القيم كأوّل وسيط لها. ستُستخدَم القيم في المصفوفة للعثور على المستخدم في جدول قاعدة البيانات. لذلك، في المثال أعلاه، سيتم استرداد المستخدم من خلال قيمة عمود البريد الإلكتروني. إذا عُثِرَ على المستخدم، فستُقارن كلمة المرور المشفرة والمخزنة في قاعدة البيانات مع قيمة كلمة المرور التي مُرِّرَت إلى التابع عبر المصفوفة. ليس عليك تشفير كلمة المرور المحددة كما هو الحال مع قيمة كلمة المرور، نظرًا لأن إطار العمل سيجري تلك العملية تلقائيًا قبل مقارنتها بكلمة المرور المخزنة في قاعدة البيانات. إذا تطابقت كلمتي المرور فستبدأ جلسة استيثاق للمستخدم.

سيعيد التابع attempt القيمة true إذا كان الاستيثاق ناجحًا. خلاف ذلك، ستُعاد القيمة false.

سيعيد التابع intended توجيه المستخدم إلى عنوان URL الذي كان يحاول الوصول إليه قبل أن يتم اعتراضه بواسطة برنامج الاستيثاق الوسيط (authentication middleware). يمكن إعطاء عنوان URI احتياطي لهذا التابع في حالة عدم توافر العنوان المقصود.

تحديد شروط إضافية

إذا كنت ترغب في ذلك، يمكنك أيضًا إضافة شروط إضافية إلى استعلام الاستيثاق بالإضافة إلى البريد الإلكتروني وكلمة المرور. على سبيل المثال، قد نتحقق من أن المستخدم معلم عليه على أنَّه نشط "active":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
  // المستخدم نشط، غير محظور، وموجود .
}

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

الوصول إلى نسخة حارس محددة

يمكنك تحديد نسخة الحارس الذي ترغب في استخدامه عبر التابع guard على الواجهة Auth. هذا يسمح لك بإدارة الاستيثاق لأجزاء منفصلة من التطبيق الخاص بك باستخدام نماذج مستقلة تمامًا (separate authenticatable models) أو جداول مستخدم (user tables) مستقلة.

يجب أن يتطابق اسم الحارس الذي مُرِّرَ إلى التابع guard مع أحد الحراس الذين ضبطناها في ملف الإعدادات auth.php الخاص بك:
if (Auth::guard('admin')->attempt($credentials)) {
  //
}

تسجيل الخروج

لتسجيل خروج المستخدمين من التطبيق الخاص بك، يمكنك استخدام التابع logout في الواجهة Auth. سيؤدي ذلك إلى مسح معلومات الاستيثاق من جلسة المستخدم:
Auth::logout();

تذكر المستخدمين

إذا كنت ترغب في توفير خاصية "تذكرني" في التطبيق الخاص بك، فيجوز لك تمرير قيمة منطقية كوسيط ثاني إلى التابع attempt، والذي سيحافظ على استيثاق المستخدم إلى أجل غير مسمى، أو حتى يسجِّل الخروج يدويًا. بالطبع، يجب أن يتضمن جدول المستخدمين users الخاص بك العمود بنوع «سلسلة نصية» باسم remember_token ، والذي سيُستخدَم لتخزين رمز "تذكرني".
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
  // تم تذكر المستخدم ...
}

ملاحظة: إذا كنت تستخدم LoginController المضمّن مع Laravel، فإن المنطق الصحيح "لتذكر" المستخدمين قد بُرمِج بالفعل من خلال السمات (traits) المستخدمة بواسطة وحدة التحكم.

إذا كنت "تتذكر" المستخدمين ، فيمكنك استخدام التابع viaRemember لتحديد ما إذا كان المستخدم قد تم استيثاقه باستخدام كعكة "Remember me":
if (Auth::viaRemember()) {
  //
}

طرق الاستيثاق الأخرى

الاستيثاق على نسخة المستخدم

إذا كنت تحتاج إلى تسجيل الدخول لنسخة مستخدم موجودة مسبقاً، فيمكنك استدعاء التابع login مع نسخة المستخدم. يجب أن يكون الكائن المحدد تطبيقًا لعقد Illuminate\Contracts\Auth\Authenticatable. وبالطبع ،فإن نموذج App\User المتضمن مع Laravel ينفذ بالفعل هذه الواجهة:
Auth::login($user);
// تسجيل الدخول و “تذكر” المستخدم المعطى
Auth::login($user, true);
بالطبع، يمكنك تحديد نسخة الـحارس الذي ترغب في استخدامه :
Auth::guard('admin')->login($user);

استيثاق على مستخدم عن طريق المعرف

لتسجيل دخول مستخدم في التطبيق من خلال المعرف الخاص بهم، يمكنك استخدام التابع loginUsingId. يقبل هذا التابع المفتاح الأساسي للمستخدم الذي ترغب في الاستيثاق عليه :
Auth::loginUsingId(1);
// تسجيل الدخول و “تذكر” المستخدم المعطى...
Auth::loginUsingId(1, true);

استيثاق على مستخدم مرة واحدة

يمكنك استخدام التابع once لتسجيل مستخدم في التطبيق لطلب واحد. لن يتم استخدام أي جلسات أو ملفات تعريف ارتباط، مما يعني أن هذا التابع قد يكون مفيدًا عند إنشاء واجهة برمجة تطبيقات بلا حالة :
if (Auth::once($credentials)) {
  //
}

استيثاق الــ HTML الأساسي

توفر استيثاق HTTP القاعدية طريقة سريعة لاستيثاق مستخدمي التطبيق دون إعداد صفحة "تسجيل دخول" خاصة. للبدء ، أرفق البرمجية الوسيطة auth.basic بمسارك. يتم تضمين البرمجية الوسيطة auth.basic مع إطار عمل Laravel، لذلك لا تحتاج إلى تعريفها :
Route::get('profile', function () {
  // فقط المستخدمين المصادق عليهم يمكنهم الدخول...
})->middleware('auth.basic');

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

ملاحظة حول FastCGI

إذا كنت تستخدم PHP FastCGI، فقد لا تعمل استيثاق HTTP القاعدية بشكل صحيح خارج الصندوق. يجب إضافة الأسطر التالية إلى ملف htaccess. الخاص بك:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

الاستيثاق الأساسي للــ HTML عديم الحالة

يمكنك أيضًا استخدام استيثاق HTTP القاعدية دون تعيين ملف تعريف ارتباط خاص بمستخدم في الجلسة، وهو أمر مفيد بشكل خاص لاستيثاق واجهة برمجة التطبيقات API. للقيام بذلك، قم بتعريف البرمجية الوسيطة التي تستدعي التابع onceBasic. إذا لم يتم إرجاع أي رد بواسطة التابع السابق ، فقد يتم تمرير الطلب إلى التطبيق :
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;

class AuthenticateOnceWithBasicAuth
{
   /**
    * الإعتناء بإستعلام قادم.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure $next
    * @return mixed
    */

   public function handle($request, $next)
   {
       return Auth::onceBasic() ?: $next($request);
   }
}
  //بعد ذلك، سجّل البرمجية الوسيطة الخاصة بالمسار وأرفقها بالمسار:

Route::get('api/user', function () {

  // فقط المستخدمين المصادق عليهم يمكنهم الدخول ...
})->middleware('auth.basic.once');

تسجيل الخروج

لتسجيل خروج المستخدمين يدويًا، يمكنك استخدام التابع logout على واجهة Auth. سيؤدي ذلك إلى مسح معلومات الاستيثاق في جلسة المستخدم:
use Illuminate\Support\Facades\Auth;

Auth::logout();

استبعاد الجلسات على الأجهزة الأخرى

يوفر Laravel أيضًا آلية لإبطال و "تسجيل الخروج" من جلسات المستخدم النشطة على الأجهزة الأخرى دون إبطال جلسة العمل على أجهزتهم الحالية. قبل البدء، يجب أن تتأكد من أن البرمجية الوسيطة Illuminate\Session\Middleware\AuthenticateSession موجودة وغير محددة كتعليق في صنف app/Http/Kernel.php web مجموعة برمجية وسيطة :
'web' => [

  // ...
   \Illuminate\Session\Middleware\AuthenticateSession::class,
  // ...

],
بعد ذلك، يمكنك استخدام التابع logoutOtherDevices على واجهة Auth. يتطلب هذ ا التابع من المستخدم تقديم كلمة المرور الحالية الخاصة به، والتي يجب أن يقبلها التطبيق من خلال حقل إدخال:
use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($password);

عندما يتم استدعاء التابع logoutOtherDevices، سيتم إلغاء جلسات العمل الأخرى للمستخدم تمامًا، مما يعني أنه سيتم "تسجيل الخروج" من جميع الحراس الذين تمت الاستيثاق بواسطتهم من قبل.

إضافة حراس مخصصين

يمكنك تحديد حراس الاستيثاق الخاصين بك باستخدام التابع extend على واجهة Auth. يجب عليك وضع هذا الاستدعاء للتمديد داخل مزود الخدمة. نظرًا لأن Laravel يأتي بالفعل مع AuthServiceProvider، يمكننا وضع الشفرة في هذا المزود :
namespace App\Providers;
use App\Services\Auth\JwtGuard;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
   /**
    * تسجيل أي خدمات استيثاق مطلوبة
    *
    * @return void
    */

   public function boot()
   {
       $this->registerPolicies();
       Auth::extend('jwt', function ($app, $name, array $config) {
          // Return an instance of Illuminate\Contracts\Auth\Guard...
           return new JwtGuard(Auth::createUserProvider($config['provider']));
       });
   }
}
كما ترون في المثال أعلاه، الرد الذي يمرر إلى التابع extend يجب أن يرجع تجسيد لـ Illuminate\Contracts\Auth\Guard. تحتوي هذه الواجهة على بعض الدوال التي ستحتاج إلى برمجتها لتحديد حارس مخصص. بمجرد تحديد حارسك المخصص، يمكنك استخدام هذا الحارس في إعدادات الحراس في ملف الإعدادات auth.php الخاص بك:
'guards' => [

   'api' => [
       'driver' => 'jwt',
       'provider' => 'users',
   ],
],

حراس طلب الإغلاق

إن أبسط طريقة لبرمجة نظام استيثاق مخصص يستند إلى إستعلام HTTP هو باستخدام التابع Auth::viaRequest. يتيح لك هذا التابع تحديد عملية الاستيثاق الخاصة بك بسرعة باستخدام إغلاق واحد.

للبدء، استدع التابع Auth::viaRequest ضمن التابع boot الخاص بـ AuthServiceProvider. يقبل التابع viaRequest اسم حارس كمدخل أول له. يمكن أن يكون هذا الاسم أي سلسلة نصية تصف حارسك المخصص. يجب أن يكون المدخل الثاني للتابع عبارة عن إغلاق الذي يتلقى طلب HTTP الوارد ويعيد نسخة مستخدم أو، في حالة فشل الاستيثاق، فراغ :
use App\User;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

/**
* تسجيل أي خدمات استيثاق مطلوبة
*
* @return void
*/

public function boot()
{

   $this->registerPolicies();
   Auth::viaRequest('custom-token', function ($request) {
       return User::where('token', $request->token)->first();

   });
}
بمجرد تحديد حارسك المخصص، يمكنك استخدام هذا الحارس في إعدادات الحراس في ملف الإعدادات auth.php الخاص بك:
'guards' => [

   'api' => [
       'driver' => 'custom-token',
   ],
],

إضافة موفري مستخدم مخصصين

إذا كنت لا تستخدم قاعدة بيانات علائقية تقليدية لتخزين المستخدمين، فستحتاج إلى تمديد Laravel مع موفر المستخدم للاستيثاق الخاص بك. سنستخدم التابع provider على واجهة Auth لتحديد موفر مستخدم مخصص:
namespace App\Providers;

use Illuminate\Support\Facades\Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider

{

   /**
    * تسجيل أي خدمات استيثاق مطلوبة
    * @return void
    */

   public function boot()
   {

       $this->registerPolicies();
       Auth::provider('riak', function ($app, array $config) {

          // إعادة نسخة عن : Illuminate\Contracts\Auth\UserProvider...
           return new RiakUserProvider($app->make('riak.connection'));
       });
   }
}
بعد تسجيل الموفر باستخدام التابع provider، يمكنك التبديل إلى موفر المستخدم الجديد في ملف الإعدادات auth.php. أولاً، حدد موفر يستخدم برنامج التشغيل الجديد الخاص بك:
'providers' => [

   'users' => [
       'driver' => 'riak',
   ],
],
أخيرًا ، يمكنك استخدام هذا الموفر في إعدادات الحراس الخاصة بك:
'guards' => [

   'web' => [
       'driver' => 'session',
       'provider' => 'users',
   ],
],

عقد مزود المستخدم

تعتبر تطبيقات Illuminate\Contracts\Auth\UserProvider مسؤولة فقط عن تنفيذ تطبيق Illuminate\Contracts\Auth\Authenticatable خارج نظام تخزين مستمر، مثل MySQL و Riak وغيرها. تسمح هاتان الواجهتان لآليات استيثاق Laravel بمواصلة العمل بغض النظر عن كيفية تخزين بيانات المستخدم أو نوع الصنف المستخدم لتمثيلها.

دعونا نلقي نظرة على عقد Illuminate\Contracts\Auth\UserProvider :
namespace Illuminate\Contracts\Auth;

interface UserProvider {

   public function retrieveById($identifier);
   public function retrieveByToken($identifier, $token);
   public function updateRememberToken(Authenticatable $user, $token);
   public function retrieveByCredentials(array $credentials);
   public function validateCredentials(Authenticatable $user, array $credentials);

}

يستلم التابع retrieveById عادة مفتاحاً يمثل المستخدم، مثل مُعرِّف تزايدي تلقائي من قاعدة بيانات MySQL. برمجية Authenticatable التي تطابق المعرف يجب أن تسترجع وتعاد بواسطة التابع.

يسترد االتابع retrieveByToken مستخدمًا مع معرفه الوحيد identifier$ و الرمز المميز "تذكرني"، المسجل في حقل remember_token. كما هو الحال مع الطريقة السابقة، يجب إرجاع برمجية Authenticatable.

يقوم التابع updateRememberToken بتحديث حقل المستخدم remember_token بالرمز المميز الجديد. يتم تعيين رمز مميز جديد لمحاولة تسجيل الدخول الناجحة "تذكرني" أو عندما يقوم المستخدم بتسجيل الخروج.

يتلقى التابع retrieveByCredentials مصفوفة بيانات الاعتماد التي تم تمريرها إلى التابع Auth::attempt عند محاولة تسجيل الدخول إلى التطبيق. التابع عليه بعدها أن "يستعلم" في التخزين الدائم الأساسي، للمستخدم مطابقة أوراق الاعتماد تلك. عادةً، سيقوم التابع بتشغيل استعلام يحتوي على شرط "where" على ['credentials['username. يجب أن يقوم التابع بإرجاع برمجية Authenticatable. يجب ألا يحاول التابع إجراء التحقق من صحة كلمة المرور أو الاستيثاق عليها.

يجب أن يقارن التابع validateCredentials المستخدم مع بيانات الاعتماد للاستيثاق على المستخدم. على سبيل المثال، من المحتمل أن تستخدم التابع Hash::check لمقارنة قيمة user->getAuthPassword()$  بقيمة ['credentials['password$. يجب أن يرجع التابع صوابًا أو خطأً true أو false مما يشير إلى ما إذا كانت كلمة المرور صالحة.

العقد المصادق عليه

الآن بعد أن اكتشفنا كل تابع من توابع UserProvider، لنلقي نظرة على عقد Authenticatable. تذكر، يجب على الموفر إرجاع برمجيات هذه الواجهة من التوابع  retrieveById, retrieveByToken، و retrieveByCredentials :
namespace Illuminate\Contracts\Auth;

interface Authenticatable {

   public function getAuthIdentifierName();
   public function getAuthIdentifier();
   public function getAuthPassword();
   public function getRememberToken();
   public function setRememberToken($value);
   public function getRememberTokenName();

}

هذه الواجهة بسيطة. يجب أن يرجع التابع getAuthIdentifierName اسم حقل "المفتاح الأساسي" للمستخدم ويجب أن يرجع التابع getAuthIdentifier "المفتاح الأساسي" للمستخدم. في خلفية MySQL، مرة أخرى، سيكون هذا المفتاح الأساسي تزايد تلقائي. يجب أن يقوم getAuthPassword بإرجاع كلمة المرور المجزئة الخاصة بالمستخدم. تسمح هذه الواجهة لنظام الاستيثاق بالعمل مع أي صنف للمستخدم، بغض النظر عن أي ORM أو طبقة تخزين مجرة، تستخدمها. افتراضياً، يتضمن Laravel صنف مستخدم في مجلد التطبيق الذي يقوم بتنفيذ هذه الواجهة، لذا يمكنك استشارة هذا الصنف للحصول على مثال للتنفيذ.

الأحداث

يثير Laravel مجموعة متنوعة من الأحداث أثناء عملية الاستيثاق. يمكنك إرفاق المستمعين بهذه الأحداث في EventServiceProvider :
/**
* ربط منصت الأحداث للتطبيق
*
* @var array
*/

protected $listen = [

   'Illuminate\Auth\Events\Registered' => [
       'App\Listeners\LogRegisteredUser',
   ],

   'Illuminate\Auth\Events\Attempting' => [
       'App\Listeners\LogAuthenticationAttempt',
   ],

   'Illuminate\Auth\Events\Authenticated' => [
       'App\Listeners\LogAuthenticated',
   ],

   'Illuminate\Auth\Events\Login' => [
       'App\Listeners\LogSuccessfulLogin',

   ],

   'Illuminate\Auth\Events\Failed' => [
       'App\Listeners\LogFailedLogin',
   ],

   'Illuminate\Auth\Events\Logout' => [
       'App\Listeners\LogSuccessfulLogout',
   ],

   'Illuminate\Auth\Events\Lockout' => [
       'App\Listeners\LogLockout',
   ],

   'Illuminate\Auth\Events\PasswordReset' => [
       'App\Listeners\LogPasswordReset',
   ],

];

مصادر