12/08/2018, 14:41

Hướng dẫn sử dụng jwt token với laravel P2

Lời mở đầu Ở bài trước mình đã giới thiệu cho các bạn về thừ viện jwt-auth , một thư viện để Authentication tuyệt vời ... Ngày hôm nay, mình sẽ giới thiệu nốt cho các bạn phần còn lại của nó ... Nào, bây giờ thì chúng ta bắt đầu nhé ! III : Tạo một token đơn giản 1, Tạo một token dự trên ...

Lời mở đầu

Ở bài trước mình đã giới thiệu cho các bạn về thừ viện jwt-auth , một thư viện để Authentication tuyệt vời ... Ngày hôm nay, mình sẽ giới thiệu nốt cho các bạn phần còn lại của nó ... Nào, bây giờ thì chúng ta bắt đầu nhé !

III : Tạo một token đơn giản

1, Tạo một token dự trên thông tin người dùng . Với một App hoặc web thông thường, cách phổ biến nhất đó là nhận về một mã xác nhận thông qua xác thực thông tin đăng nhập của họ . Ví dụ như chúng ta có một AuthenticateController đơn giản như sau :

Laravel 5 :

use JWTAuth;
use TymonJWTAuthExceptionsJWTException;

class AuthenticateController extends Controller
{
    public function authenticate(Request $request)
    {
        // lấy thông tin từ các request gửi lên
        $credentials = $request->only('email', 'password');

        try {
            // xác nhận thông tin người dùng gửi lên có hợp lệ hay không
            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'invalid_credentials'], 401);
            }
        } catch (JWTException $e) {
            // Xử lý ngoại lệ 
            return response()->json(['error' => 'could_not_create_token'], 500);
        }

        // xác nhận thành công thì trả về 1 token hợp lệ
        return response()->json(compact('token'));
    }
}

Laravel 4

use TymonJWTAuthExceptionsJWTException;

class AuthenticateController extends Controller
{
    public function authenticate()
    {
        // lấy thông tin từ các request gửi lên
        $credentials = Input::only('email', 'password');

        try {
            // xác nhận thông tin người dùng gửi lên có hợp lệ hay không
            if (! $token = JWTAuth::attempt($credentials)) {
                return Response::json(['error' => 'invalid_credentials'], 401);
            }
        } catch (JWTException $e) {
            //  Xử lý ngoại lệ 
            return Response::json(['error' => 'could_not_create_token'], 500);
        }

        // xác nhận thành công thì trả về 1 token hợp lệ
        return Response::json(compact('token'));
    }
}

2, Tạo token dự trên một đối tượng .

Ngoài phương pháp thông thường, chúng ta còn có thể tạo một mã xác nhận dựa trên một một đối tượng người dụng như sau :

// grab some user
$user = User::first();

$token = JWTAuth::fromUser($user);

Với 2 cách trên chúng ta có thể tạo token nhưng nếu bạn muốn ghi thêm dữ liệu vào token thì có thể sử dụng thêm tham số thứ 2 như là lơi ghi thêm dữ liệu ... Cụ thể như sau :

$customClaims = ['foo' => 'bar', 'baz' => 'bob'];

JWTAuth::attempt($credentials, $customClaims);
// or
JWTAuth::fromUser($user, $customClaims);

Và đương nhiên, những dữ liệu bạn ghi thêm vào sẽ có mặt cùng với những dữ liệu khác khi giải mã token.

Lưu ý: Hết sức chú ý những dữ liệu bạn ghi thêm vào token vì chúng sẽ làm tăng độ dài cũng như dung lượng của token

3: Tạo một đoạn token từ bất kì điều gì bạn muốn.

Nếu bạn muốn tạo 1 free rule từ đâu đó thì bạn có thể dùng cách sau :

$customClaims = ['foo' => 'bar', 'baz' => 'bob'];

$payload = JWTFactory::make($customClaims);

$token = JWTAuth::encode($payload);

IV : Xác thực

Ok, khi bạn đã có mã token của riêng mình, việc còn lai chỉ là làm cách nào để xác thực xem đoạn mã có đúng hay còn hiệu lực hay không. Hay nói một cách đơn giản hơn thì khi bạn đã đăng nhập thành công thì làm thế nào để server hiểu bạn đang đăng nhập hay không.

Để làm được điều này thì jwt-token đã đưa ra một phương pháp khá hay , tức là với mỗi request gửi lên server thì cần gắn liều token, với token này thì server có thể lấy được thông tin đăng nhập .

Ok nói thì có vẻ hơi khó hiểu, nói đơn giản thì với request bạn gửi lên server thì cần set thêm 1 đoạn mã vào header gửi đi. Đoạn mã đó có dạng như sau :

Authorization: Bearer {your_token_here}

Với những người dùng máy chủ là Apache thì cần chú ý là cần phải fix đoạn mã sau vào Apache config :

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

Hoặc nếu bạn không muốn sử dụng header thì có thể sử dụng query string . Ví dụ

http://api.mysite.com/me?token={your_token_here}

Để lấy token từ đoạn mã gửi lên thì bạn có thể làm như sau:

JWTAuth::parseToken();
$user = JWTAuth::parseToken()->authenticate();

Để lấy giá trị token thì có thể làm như sau :

$token = JWTAuth::getToken();

Và tất nhiên khi cần thiết, bạn cũng có thể set token khi cần thiết:

JWTAuth::setToken('foo.bar.baz');

Ví dụ:

public function getAuthenticatedUser()
{
    try {

        if (! $user = JWTAuth::parseToken()->authenticate()) {
            return response()->json(['user_not_found'], 404);
        }

    } catch (TymonJWTAuthExceptionsTokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (TymonJWTAuthExceptionsTokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    } catch (TymonJWTAuthExceptionsJWTException $e) {

        return response()->json(['token_absent'], $e->getStatusCode());

    }

    return response()->json(compact('user'));
}

Nếu bạn không muốn tự bặt các ngoại lệ của token , thì có 1 cách đó là sử dụng cách bắt exception global:

Laravel 4:

Thêm đoạn mã sau vào file app/start/global.php

App::error(function(TymonJWTAuthExceptionsJWTException $e, $code)
{
    if ($e instanceof TymonJWTAuthExceptionsTokenExpiredException) {
        return Response::json(['token_expired'], $e->getStatusCode());
    } else if ($e instanceof TymonJWTAuthExceptionsTokenInvalidException) {
        return Response::json(['token_invalid'], $e->getStatusCode());
    }
});

Laravel 5: Thêm đoạn mã sau vào file app/Exceptions/Handler.php:

public function render($request, Exception $e)
{
    if ($e instanceof TymonJWTAuthExceptionsTokenExpiredException) {
        return response()->json(['token_expired'], $e->getStatusCode());
    } else if ($e instanceof TymonJWTAuthExceptionsTokenInvalidException) {
        return response()->json(['token_invalid'], $e->getStatusCode());
    }

    return parent::render($request, $e);
}

Middleware and Filters

Laravel 4 : Với phiên bản này, chúng ta có thê dùng jwt-auth filter. Nó bao gồm một số hành động mặc định hợp lý khi xảy ra lỗi của token (hết hạn, sai ..v..v..) Cụ thể như sau :

Route::post('me', ['before' => 'jwt-auth', function() {

    $user = JWTAuth::parseToken()->toUser();

    return Response::json(compact('user'));
}]);

Nếu bạn muốn custom lại các hành động mạc định này thì có thê định nghĩ lại các event sau :

Event::listen('tymon.jwt.absent');

Event::listen('tymon.jwt.expired');

Event::listen('tymon.jwt.invalid');

Event::listen('tymon.jwt.user_not_found');

Event::listen('tymon.jwt.valid');

Laravel 5 : Với laravel 5 thì ta thể sử dụng 2 middleware:

  • GetUserFromToken : Middleware này có tác dung tác dụng tương tự giống như filter của laravel 4

  • RefreshToken : Middleware này cũng có tác dụng như Middleware trên tuy nhiên, nó trả vể 1 đoạn token mới đã đk reset cho người dùng và vô hiệu hóa token cũ ... Nó giúp sử dụng linh hoạt các token, tránh việc sử dụng quá nhiều lần 1 token.

Note: Để sử dụng 2 middleware này thì chúng ta cần khai báo trong app/Http/Kernel.php như các middleware khác nhé :

protected $routeMiddleware = [
    ...
    'jwt.auth' => 'TymonJWTAuthMiddlewareGetUserFromToken',
    'jwt.refresh' => 'TymonJWTAuthMiddlewareRefreshToken',
];

Ok, vậy là mình đã giới thiệu hết về jwt-token rồi, cám ơn các bạn đã đọc hết bài viết này! Hy vọng bài viết sẽ hữu ích cho các bạn .

TÀI LIỆU THAM KHẢO

  • Tìm hiểu về json web token
  • Jwt-auth
0