آموزش احرازهویت به سبک JWT در لاراول

JWT (Json Web Token) چیه؟

JWT یا JSON Web Token یک استاندارد برای انتقال ایمن اطلاعات بین دو طرف است که داده‌ها را در قالب JSON منتقل می‌کند. JWT معمولاً در سیستم‌های احراز هویت و مجوزدهی کاربرد دارد و به سرورها این امکان را می‌دهد که بدون نگه‌داشتن اطلاعات نشست (session) در سمت خود، هویت کاربران را بررسی کنند.

JWT از سه بخش تشکیل شده است:

  1. Header (سربرگ): شامل اطلاعاتی درباره نوع توکن و الگوریتم رمزنگاری استفاده‌شده.

  2. Payload (بار): داده‌های موردنظر را شامل می‌شود، مثل شناسه کاربر یا زمان انقضای توکن.

  3. Signature (امضا): تضمین می‌کند که داده‌ها در طول مسیر تغییر نکرده‌اند و توسط صادرکننده اصلی ایجاد شده‌اند.

کار اصلی JWT این است که پس از احراز هویت موفق کاربر (مثلاً ورود به سایت)، یک توکن تولید می‌شود و به کاربر داده می‌شود. کاربر در درخواست‌های بعدی این توکن را به همراه درخواست‌هایش ارسال می‌کند و سرور بدون نیاز به نگه داشتن وضعیت، با بررسی امضای توکن، هویت کاربر را تأیید می‌کند.


1. نصب پکیج JWT

خب برای شروع باید پکیج tymon/jwt-auth رو نصب کنیم که با دستور زیر نصب میشه:

composer require tymon/jwt-auth

بعد از نصب پکیج نیاز داریم فایل های کانفیگ رو پابلیش کنیم:

php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"

با اجرا این دستور یک فایل کانفیگ به نام config/jwt.php ایجاد میشه.


2. ساخت کلید secret برای JWT

دستور زیر برای ساخت کلید اجرا کنید:

php artisan jwt:secret

حالا این کلید ساخته شده در فایل .env قرار دهید:

JWT_SECRET=strong_secret_word



3. کانفیگ کردن گارد احرازهویت

فایل config/auth.php رو ویرایش کنید و گارد api تغییر بدید به jwt:

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


4. ویرایش مدل User

در مدل User (اصولا در پوشه app/Models باید باشه)، باید از اینترفیس JWTSubject استفاده کنید:

use TymonJWTAuthContractsJWTSubject;

class User extends Authenticatable implements JWTSubject
{
    /**
     * Get the identifier that will be stored in the JWT token.
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return an array with custom claims to be added to the JWT token.
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}


5. ساخت کنترلر AuthController

با دستور زیر یک کنترلر ایجاد کنید:

php artisan make:controller AuthController

حالا کنترلر باز کنید و متد های register، login و logout درونش پیاده سازی کنید:

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppModelsUser;
use IlluminateSupportFacadesHash;
use IlluminateSupportFacadesAuth;
use TymonJWTAuthFacadesJWTAuth;
use TymonJWTAuthExceptionsJWTException;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        try {
            $token = JWTAuth::fromUser($user);
        } catch (JWTException $e) {
            return response()->json(['error' => 'Could not create token'], 500);
        }

        return response()->json([
            'token' => $token,
            'user' => $user,
        ], 201);
    }

    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        try {
            if (!$token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'Invalid credentials'], 401);
            }
        } catch (JWTException $e) {
            return response()->json(['error' => 'Could not create token'], 500);
        }

        return response()->json([
            'token' => $token
            'expires_in' => auth('api')->factory()->getTTL() * 60,
        ]);
    }

    public function logout()
    {
        try {
            JWTAuth::invalidate(JWTAuth::getToken());
        } catch (JWTException $e) {
            return response()->json(['error' => 'Failed to logout, please try again'], 500);
        }

        return response()->json(['message' => 'Successfully logged out']);
    }

    public function getUser()
    {
        try {
            $user = Auth::user();
            if (!$user) {
                return response()->json(['error' => 'User not found'], 404);
            }
            return response()->json($user);
        } catch (JWTException $e) {
            return response()->json(['error' => 'Failed to fetch user profile'], 500);
        }
    }

    public function updateUser(Request $request)
    {
        try {
            $user = Auth::user();
            $user->update($request->only(['name', 'email']));
            return response()->json($user);
        } catch (JWTException $e) {
            return response()->json(['error' => 'Failed to update user'], 500);
        }
    }
}


6. ساخت Middleware مخصوص JWT

با استفاده از دستور زیر یک میدلور برای چک کردن توکن JWT میسازیم:

php artisan make:middleware JwtMiddleware

با استفاده از متد "()authenticate" میایم توکن کاربر بررسی میکنیم:

namespace AppHttpMiddleware;

use Closure;
use TymonJWTAuthFacadesJWTAuth;
use Exception;
use IlluminateHttpRequest;

class JwtMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        try {
            JWTAuth::parseToken()->authenticate();
        } catch (Exception $e) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $next($request);
    }
}

در لاراول 12، شما برای رجیستر کردن یک میدلور در لاراول از فایل boostrap/app.php استفاده میکنیم (آموزش کار با میدلور ها (Middleware) در لاراول):

->withMiddleware(function (Middleware $middleware) {
    //
    $middleware->alias([
        'jwt' => JwtMiddleware::class
    ]);
})


7. ایجاد روت های API

فایل routes/api.php باز کنید و روت های زیر پیاده سازی کنید:

use AppHttpControllersAuthController;
use IlluminateSupportFacadesRoute;

Route::get('/', function () {
    return response()->json(['message' => 'Hello world!']);
});

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

Route::middleware('jwt')->group(function () {
    Route::get('/user', [AuthController::class, 'getUser']);
    Route::post('/logout', [AuthController::class, 'logout']);
    Route::put('/user', [AuthController::class, 'updateUser']);
});

در روت ها میبینید از میدلور jwt استفاده کردیم که نیازمند توکن هست.


امیدوارم کاربردی باشه💜

0 🔥
0 🎉
0 😮
0 👍
0 💜
0 👏
میلاد خسروی
نویسنده کد نیوز

برنامه نویس فان | Fun Developer یک آدم ساده که عاشق برنامه نویسی و کد زدنه :) تلاش میکنه تا به بقیه کمک کنه. توسعه دهنده هسته لاراول و فضای اوپن سورس. فاندر پرانتز و کد نیوز.

0+ نظر

برای ثبت نظر ابتدا ورود کنید.

0 نظر

    اولین نفر باش که نظر ثبت میکنی :) یعنی یه کامنت به ما نمیرسه 😁