جدول المحتويات
واحدة من أفضل أنظمة المصادقة التي يوفرها إطار العمل لارافيل، هي Laravel Sanctum حيث يوفر نظام مصادقة سريع لتطبيقات الويب SPA، وتطبيقات الهوات، وواجهات APIs، كما يسمح لكل مستخدم بإنشاء رموز API متعددة لحسابهم.
بعد تسجيل مستخدم أو القيام بعملية تسجيل الدخول، سوف يحصل المستخدم على token وفي كل طلب يتم إرسالة يجب أن يتم إرسال token حتى تتم عملية المصادقة.
في هذه المقالة سوف سيتم شرح كيفية إستخدام Laravel Sanctum في عملية المصادقة، خطوة بخطوة:-
إعداد ملف .env للإتصال بقاعدة البيانات.
DB_DATABASE=youtube DB_USERNAME=root DB_PASSWORD= redhat@123
تثبيت حزمة Laravel Sanctum
composer require laravel/sanctum
عمل publish لإعدادات حزمة Sanctum وملف migration
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
تنفيذ ملف migration لتهيئة حقل users للتعامل مع laravel Sanctum.
php artisan migrate
بعد عمل migrate سيتم إنشاء جدول جديد بإسم personal_access_tokens
إضافة Sanctum Middleware
حيث نذهب للملف kernel.php وبداخل الدالة middlewaregroup ونعدل على api بالشكل التالي
../app/Http/Kernel.php
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful; ... protected $middlewareGroups = [ ... 'api' => [ EnsureFrontendRequestsAreStateful::class, 'throttle:60,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ]; ... ],
لإستخدام sanctum tokens للـ User Model يجب إخبار UserModel بإستخدام HasApiTokens
use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, Notifiable; }
بذلك نكون قد إنتهينا من إعدادات Sanctum
إنشاء Seeder للـ User Model
php artisan make:seeder UsersTableSeeder
لإدخال البيانات في جدول Users بإستخدام UserTableSeeder نذهب للملف UserTableSeeder الموجود في المسار
database/seeders/UserTableSeeder.php
وبداخل الدالة run نضيف جمل الإدخال
class UsersTableSeeder extends Seeder { public function run() { DB::table('users')->insert([ 'name' => 'John Doe', 'email' => 'john@doe.com', 'password' => Hash::make('password') ]); } }
ولعمل seed من خلال artisan
php artisan db:seed --class=UsersTableSeeder
إضافة route في ملف api.php
Route::post('login',[UserController::class,'index']);
وللتحقق وتسجيل الدخول من خل دالة login بداخل الكلاس UserController
namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class UserController extends Controller { function login(Request $request) { $user= User::where('email', $request->email)->first(); // print_r($data); if (!$user || !Hash::check($request->password, $user->password)) { return response([ 'message' => ['These credentials do not match our records.'] ], 404); } $token = $user->createToken('my-app-token')->plainTextToken; $response = [ 'user' => $user, 'token' => $token ]; return response($response, 201); }
حيث إنه سيتحقق إذا إذا كان البريد الإلكتروني مسجل في قاعدة البيانات، ومن ثم سيتحقق من password، إذا كانت غير متوافقة سيتم إرجاع خطأ 404 ورسالة 'These credentials do not match our records.
أما إذا كانت البيانات صحيحة فإنه سيتم إرجاع المستخدم مع token والكود سيكون 201.
مع الإنتباه هنا أنه عندما تم إنشاء token تم وضع إسم لهذا token وهو my_app_token وهو إسم بمثابة key نستطيع إختيار أي إسم نريد فليس شرط أن يكون my_app_token.
لفحص تسجيل الدخول بإستخدام postman.
كما نلاحظ أنه تم إرجاع user وكذلك token.
لحماية route في ملف api.php والتأكد من أن المستخدم قام بتسجيل الدخول، يجب إضافة middleware=>auth:sanctum
Route::group(['middleware' => 'auth:sanctum'], function(){ //All secure URL's }); Route::post("login",[UserController::class,'index']);
على سبيل المثال لو كان لدي route بالشكل التالي
Route::apiResource('brands',BrandController::class);
وأريد أن لا يتم عرض / تعديل / تخزين / حذف الـ brands إلا للمستخدمين الذين قاموا بتسجيل الدخول، يجب وضع هذا route بداخل middleware=>auth:sanctum
Route::group(['middleware' => 'auth:sanctum'], function(){ Route::apiResource('brands',BrandController::class); }); Route::post("login",[UserController::class,'index']);
الأن لو حاولنا زيارة الرابط http://www.test.test/api/brands لعرض المنتجات فإننا سوف نحصل على خطأ لأنه يجب إرسال token مع كل request تم حمايته بإستخدام middleware=>auth:sanctum
ولإرسال token من خلال postman نذهب للتبويب headers ويجب إضافة
Authorization : Bearer 2|8r16cVhcsI2DyPGogVDKmSKD2g4xEBTcsi5XHQAu
حيث يجب إضافة Bearer ومن ثم token الذي تم تسجيل الدخول من خلاله.
كما نلاحظ أنه تم عرض brands بنجاح.
أما إذا كنت لا ترغب في كتابة كلمة Bearer فبالإمكان إختيار نوع Auth بأن يكون Bearer Token وكتابة token كما بالصورة أدناه.
تسجيل مستخدم جديد
بداية لتسجيل مستخدم جديد يجب إنشاء كلاس للتحقق من المدخلات، وذلك من خلال إنشاء UserRegisterRequest
class UserReqisterRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ 'name'=>'required|string', 'email'=>'required|string|unique:users,email', 'password'=>'required|string|confirmed', ]; } }
وفي دالة store بداخل UserController سيتم تسجيل المستخدم
public function register(UserReqisterRequest $request){ $user=new User(); $user->name=$request->name; $user->email=$request->email; $user->password=Hash::make($request->password); $user->save(); $token=$user->createToken('my-app-token')->plainTextToken; $respons=[ 'user'=>$user, 'token'=>$token ]; return $respons; }
ولإرسال البيانات من خلال postman
خطوات تسجيل الخروج:-
إنشاء route لتسجيل الخروج
Route::group(['middleware' => 'auth:sanctum'], function(){ Route::apiResource('brands',BrandController::class); Route::post('logout',[UserController::class,'logout']); });
إنشاء دالة logout بداخل UserController
public function logout(Request $request){ auth()->user()->tokens()->delete(); }
الحذف من خلال postman
حيث يجب إرسال token الخاص بالمستخدم الذي سيتم عمل تسجيل خروج له.
حيث سيتم حذف token التابع للمستخدم الذي تم إرسال token له من جدول personal_access_tokens.
توفر لنا Sanctum التحكم بالصلاحيات، حيث يتم ذلك من خلال إضافة مصفوفة بالصلاحيات إلى token، على سبيل المثال لإضافة صلاحية brand-list، ومن لديه هذه الصلاحية يستطيع عرض brands
إضافة الصلاحية بإسم brand-list
$token=$user->createToken('my-app-token',['brand-list'])->plainTextToken;
وللتحقق من الصلاحية، نذهب لدالة عرض brand في brandController ونستخدم tokenCan
public function index() { if(!auth()->user()->tokenCan('brand-list')){ abort(403,'UnAuthorized'); } return Brand::get(); }
اين يتم إضافة هذا الكود $token=$user->createToken(\'my-app-token\',[\'brand-list\'])->plainTextToken;
شككرا على مجهودك لو سمحت لدي استفسار مالفرق بين Sanctum و passport ومتى نستخدم هذه أو تلك؟
بستفيد جددا من مقالات حضرتك الله يحفظك يارب , ويتريت تستمر ♥
مقال رهيب، شكرا يا ايثار ❤️
مقال رهيب، شكرا يا ايثار ❤️
واثق الشويطر
مقالات جميلة .. شكرا لك..