JWT hoặc session-based authentication

Tạo bởi Hoàng Vũ, chỉnh sửa cuối lúc 9 tháng 6, 2025

Sau khi đã hiểu cơ chế đăng nhập cơ bản, bài học này giúp bạn triển khai xác thực thực tế bằng JWT (dùng cho REST API) hoặc Session (dùng cho ứng dụng truyền thống). Bạn sẽ học cách mã hóa, giải mã JWT và lưu thông tin đăng nhập để tái sử dụng trong ứng dụng.

Mục tiêu

  • Áp dụng JWT để xác thực trong RESTful API.
  • Quản lý đăng nhập bằng session.
  • Phân biệt giữa session-based và token-based authentication.

1 JWT Authentication (API)

a. Cài thư viện JWT:

composer require firebase/php-jwt

b. Tạo JWT khi đăng nhập:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey = "your_secret_key";

$app->post('/api/login', function ($request, $response) use ($secretKey) {
    $data = $request->getParsedBody();
    $username = $data['username'];
    $password = $data['password'];

    if ($username === 'admin' && $password === '123456') {
        $payload = [
            'iss' => 'slim-api',
            'sub' => $username,
            'iat' => time(),
            'exp' => time() + 3600
        ];
        $jwt = JWT::encode($payload, $secretKey, 'HS256');
        return $response->withJson(['token' => $jwt]);
    }

    return $response->withJson(['error' => 'Unauthorized'], 401);
});

c. Middleware xác thực JWT:

$jwtMiddleware = function ($request, $handler) use ($secretKey) {
    $authHeader = $request->getHeaderLine('Authorization');
    if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
        $jwt = $matches[1];
        try {
            $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
            $request = $request->withAttribute('user', $decoded->sub);
            return $handler->handle($request);
        } catch (Exception $e) {
            return (new Slim\Psr7\Response())->withStatus(401)->withHeader('Content-Type', 'application/json')
                ->getBody()->write(json_encode(['error' => 'Invalid token']));
        }
    }
    return (new Slim\Psr7\Response())->withStatus(401)->withHeader('Content-Type', 'application/json')
        ->getBody()->write(json_encode(['error' => 'Token not provided']));
};

d. Sử dụng middleware:

$app->get('/api/profile', function ($request, $response) {
    $user = $request->getAttribute('user');
    return $response->withJson(['username' => $user]);
})->add($jwtMiddleware);

2 Session-based Authentication (Truyền thống)

a. Lưu session khi login:

session_start();

$app->post('/login', function ($request, $response) {
    $data = $request->getParsedBody();
    if ($data['username'] === 'admin' && $data['password'] === '123456') {
        $_SESSION['user'] = $data['username'];
        return $response->withRedirect('/dashboard');
    }
    return $response->write('Sai tài khoản hoặc mật khẩu');
});

b. Middleware kiểm tra đăng nhập:

$authMiddleware = function ($request, $handler) {
    if (!isset($_SESSION['user'])) {
        return (new Slim\Psr7\Response())->withStatus(302)->withHeader('Location', '/login');
    }
    return $handler->handle($request);
};

$app->get('/dashboard', function ($request, $response) {
    return $response->write("Chào mừng, " . $_SESSION['user']);
})->add($authMiddleware);

Kết luận

  • JWT phù hợp với các API RESTful không trạng thái.
  • Session đơn giản hơn, phù hợp với ứng dụng truyền thống có giao diện HTML.
  • Middleware là công cụ cốt lõi để bảo vệ các route yêu cầu xác thực.

Bài tập thực hành

  1. Cài đặt thư viện JWT:

    • Dùng composer require firebase/php-jwt.
  2. Tạo route login trả JWT:

    • Nếu đăng nhập đúng, trả token chứa usernameexp.
  3. Tạo middleware xác thực JWT:

    • Nếu token hợp lệ, cho phép truy cập route /api/profile.
  4. Session login:

    • Tạo form login truyền thống lưu $_SESSION['user'].
    • Bảo vệ route /dashboard bằng session middleware.
Website Logo

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.

Bình luận

Website Logo

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.

Liên hệ công việc qua email dưới đây.

lhvuctu@gmail.com

Chúng Tôi Trên

Bạn đang muốn học về lập trình website?

Bạn cần nâng cao kiến thức chuyên nghiệp hơn để nâng cao cơ hội nghề nghiệp? Liên hệ