Hướng dẫn php decode jwt token

Với sự hoành tráng của mô hình client server -- WEB API thì khái niệm api không còn lạ với chúng ta nữa. Với sự hoành tráng của mô hình client server -- WEB API thì khái niệm api không còn lạ với chúng ta nữa. 

2021-07-06 2980 lượt xem

  1. Trang Chủ
  2. laravel
  3. Hướng dẫn sử dụng jwt token với laravel php sử dụng thư viện tymon auth

hùng thông minh lắm

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

Hướng dẫn php decode jwt token

ahihi đồ ngốc trương thanh hùng nè

hùng thông minh lắm

hùng đẹp trai

tôi thích vậy đó

hùng đẹp trai

Và JWT token cũng thế, ở khuôn khổ bài này mình không nói về jwt là gì. Mình chỉ hướng dẫn cho các bạn cách nhúng jwt vào laravel cho api.

tôi thích vậy đó

hùng thông minh lắm

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

hùng thông minh lắm

hùng thông minh lắm

tôi thích vậy đó

1. cài package

hùng ebudezain

hùng ebudezain

đọc dữ liệu hộ bố

Chạy lệnh thông qua composer : 

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

composer require tymon/jwt-auth

hùng thông minh lắm

hùng ebudezain

2. config provider và alias

hùng đẹp trai

đọc dữ liệu hộ bố

ahihi đồ ngốc trương thanh hùng nè

tôi thích vậy đó

Sau khi install package hoàn tất, bạn cần thêm service provider vào mảng provider trong file config app.php :

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

hùng đẹp trai

Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,

hùng thông minh lắm

hùng đẹp trai

hùng ebudezain

cũng tại file app.config đó bạn thêm aliases cho 2 lớp thường dùng: 

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory'::class,

tôi thích vậy đó

hùng ebudezain

hùng đẹp trai

3. tạo file config để jwt hoạt động

hùng đẹp trai

tôi thích vậy đó

hùng ebudezain

hùng đẹp trai

hùng đẹp trai

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng thông minh lắm

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

Sau cùng bạn cần publish config của jwt ( kiểu như nó tạo cái file config vào hệ thống laravel )

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

hùng ebudezain

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

tôi thích vậy đó

hùng đẹp trai

đọc dữ liệu hộ bố

tôi thích vậy đó

hùng ebudezain

4. Tạo secret key

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

Theo lý thuyết jwt dĩ nhiên muốn tạo ra 1 token bạn cần cung cấp 1 secret key 
tạo secret key trong laravel khá dễ : 

ahihi đồ ngốc trương thanh hùng nè

hùng ebudezain

đọc dữ liệu hộ bố

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

tôi thích vậy đó

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

hùng thông minh lắm

tôi thích vậy đó

hùng đẹp trai

Nếu bạn sử dụng jwt để thực hiện xác thực cho việc trao đổi thông tin giữa 2 server 
thì 2 key của 2 server phải giống nhau thì mới có thể giải mã được ... 

Vì vậy, bạn có thể tạo 1 key bất kỳ bên server này và copy cho server kia. 

hùng ebudezain

hùng thông minh lắm

hùng đẹp trai

ahihi đồ ngốc trương thanh hùng nè

hùng ebudezain

ahihi đồ ngốc trương thanh hùng nè

hùng đẹp trai

bài hướng dẫn giải mã jwt của php laravel trong nodejs 

hùng đẹp trai

5. sửa lại model user để tiêm cái id user vào claim

tôi thích vậy đó

bạn cần implements cái interface tên JWTSubject và thực thi 2 phương thức getJWTIdentifier, getJWTCustomClaims mục tiêu là để khi tạo token thì jwt của bạn được gắn chặt với 1 vái value là id của user. Sau đó khi giải mã thì ta được 1 object user tương ứng

hùng thông minh lắm

hùng ebudezain

hùng ebudezain

hùng đẹp trai

namespace App\Models;

/// ... 
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

     /**
     * @return int
     */
    public function getJWTIdentifier() {
        
        return $this->getKey();
    }
    
    /**
     * @return array
     */
    public function getJWTCustomClaims() {
        return [
            "iss" => "http://localhost",
            "ahihi" => "đồ ngốc CustomClaims"
        ];
    }
    //// ..... 
}

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

đọc dữ liệu hộ bố

hùng thông minh lắm

hùng thông minh lắm

Hướng dẫn php decode jwt token

hùng thông minh lắm

6. lưu ý thông tin file config

ahihi đồ ngốc trương thanh hùng nè

tôi thích vậy đó

đọc dữ liệu hộ bố

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

ahihi đồ ngốc trương thanh hùng nè

Secret Key - secret

đọc dữ liệu hộ bố

ahihi đồ ngốc trương thanh hùng nè

Cái tên nói lên tất cả 😄 Mục 4 mình vừa trình bày là cái key này, khi bạn muốn 2 server giải mã qua lại thì 2 server phải có key giống nhau.
Mặc định load trong env cái biến JWT_SECRET không thì nó lấy đại 

hùng thông minh lắm

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

tôi thích vậy đó

tôi thích vậy đó

'secret' => env('JWT_SECRET', 'hung-dep-trai'),

tôi thích vậy đó

hùng đẹp trai

tôi thích vậy đó

JWT time to live - ttl

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

tôi thích vậy đó

tôi thích vậy đó

đọc dữ liệu hộ bố

hùng ebudezain

1 token tạo ra phải có thười gian sống (tính bằng phút). Khuyến nghị ngắn thôi. 

hùng ebudezain

tôi thích vậy đó

tôi thích vậy đó

hùng thông minh lắm

tôi thích vậy đó

Refresh time to live - refresh_ttl

ahihi đồ ngốc trương thanh hùng nè

Đây là thời gian (tính bằng phút) bạn có thể tạo mới một token khác từ token cũ mà ko cần xác thực lại... 

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng thông minh lắm

'refresh_ttl' => 20160, //2 week

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng đẹp trai

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

hùng thông minh lắm

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

hùng thông minh lắm

Tạo một token dự trên user

tôi thích vậy đó

hùng thông minh lắm

đọc dữ liệu hộ bố

ahihi đồ ngốc trương thanh hùng nè

tôi thích vậy đó

hùng thông minh lắm

đọc dữ liệu hộ bố

ahihi đồ ngốc trương thanh hùng nè

class LoginCotnroller trong thư mục api như sau: 

hùng đẹp trai

hùng ebudezain

ahihi đồ ngốc trương thanh hùng nè

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()
                    ->error(
                        'có lỗi validate trong controller', 
                        ['error' => 'invalid_credentials'],
                        Response::HTTP_UNAUTHORIZED
                    )
                    ->setStatusCode(Response::HTTP_UNAUTHORIZED);
            }
        } catch (JWTException $e) {
            // Xử lý ngoại lệ 
            return response()
                    ->error(
                        'có lỗi validate trong controller', 
                        ['error' => 'could_not_create_token'],
                        Response::HTTP_INTERNAL_SERVER_ERROR
                    )
                    ->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
        }

        return response()
                    ->success('Your custom login', $token)
                    ->setStatusCode(Response::HTTP_OK);
    }

    /**
     * Nếu bạn sử dụng function login ở trên nhìn thấy phức tạp hay thấy gớm, khó hiểu quá thì dùng function dưới này nhìn dễ hiểu hơn 1 tí :D
     */
    public function simpleLogin(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'));
    }
}

 

tôi thích vậy đó

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

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

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

đọc dữ liệu hộ bố

hùng thông minh lắm

ahihi đồ ngốc trương thanh hùng nè

hùng đẹp trai

hùng đẹp trai

ahihi đồ ngốc trương thanh hùng nè

Ngoài phương pháp thông thường, 
chúng ta còn có thể tạo một mã Token dựa trên một user instance như sau :

hùng thông minh lắm

hùng đẹp trai

hùng đẹp trai

$user = User::where('email', '')->first();
if(!$user){
    return response()->json(['error' => 'user_not_found'], 500);
}

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

hùng đẹp trai

hùng ebudezain

hùng ebudezain

ahihi đồ ngốc trương thanh hùng nè

claims - ghi thêm dữ liệu vào token

hùng thông minh lắm

tôi thích vậy đó

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

// JWTAuth::attempt($credentials, $customClaims); -> phương thức để login
// or
JWTAuth::fromUser($user, $customClaims);

hùng ebudezain

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

đọc dữ liệu hộ bố

hùng đẹp trai

đọc dữ liệu hộ bố

hùng đẹp trai

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

đọc dữ liệu hộ bố

ahihi đồ ngốc trương thanh hùng nè

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.

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

đọc dữ liệu hộ bố

hùng ebudezain

đọc dữ liệu hộ bố

hùng thông minh lắm

hùng thông minh lắm

hùng ebudezain

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

đọc dữ liệu hộ bố

hùng ebudezain

ahihi đồ ngốc trương thanh hùng nè

tôi thích vậy đó

Tạo token từ 1 object bất kì

tôi thích vậy đó

hùng ebudezain

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

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

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

đọc dữ liệu hộ bố

hùng thông minh lắm

Xác thực

tôi thích vậy đó

Có token rồi thì khi người dùng gọi api phải gửi lên kèm header hoặc query params 
Với token này thì server có thể check token đó đúng không ? nếu đúng thì lấy được thông tin đăng nhập .

hùng đẹp trai

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

Đoạn mã đó có dạng như sau :

tôi thích vậy đó

tôi thích vậy đó

ahihi đồ ngốc trương thanh hùng nè

hùng ebudezain

đọc dữ liệu hộ bố

Authorization: Bearer {your_token_here}

đọc dữ liệu hộ bố

tôi thích vậy đó

đọc dữ liệu hộ bố

hùng ebudezain

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

ví dụ cụ thể: 

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

đọc dữ liệu hộ bố

GET /api/v1/users HTTP/1.1
Host: localhost:80
User-Agent: rest-client
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6,zh-CN;q=0.4
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2FwaVwvdjFcL2xvZ2luIiwiaWF0IjoxNjI1NTMwNDY2LCJleHAiOjE2MjU1MzQwNjYsIm5iZiI6MTYyNTUzMDQ2NiwianRpIjoibFhCZUlmMFFOMk9rTGlOZSIsInN1YiI6MiwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.nAGhQWgLSPd-yX_xMRvNn82NZpXjMBKY61G0FHiIxV0
content-type: application/json
################################

hùng thông minh lắm

tôi thích vậy đó

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

hùng thông minh lắm

đọc dữ liệu hộ bố

hùng đẹp trai


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

hùng thông minh lắm

hùng đẹp trai

hùng đẹp trai

http://domain.xyz/users?token={your_token_here}

hùng đẹp trai

đọc dữ liệu hộ bố

tôi thích vậy đó

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

ahihi đồ ngốc trương thanh hùng nè

hùng ebudezain

hùng thông minh lắm

đọc dữ liệu hộ bố

tôi thích vậy đó

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

hùng đẹp trai

hùng đẹp trai

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

hùng thông minh lắm

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

hùng thông minh lắm

đọc dữ liệu hộ bố

tôi thích vậy đó

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

hùng thông minh lắm

đọc dữ liệu hộ bố

$token = JWTAuth::getToken();

hùng đẹp trai

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

đọc dữ liệu hộ bố

hùng đẹp trai

public function getAuthenticatedUser()
{
    try {

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

    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

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

    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

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

    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

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

    }

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

hùng ebudezain

ahihi đồ ngốc trương thanh hùng nè

đọc dữ liệu hộ bố

exception global

đọc dữ liệu hộ bố

bài viết được viết bởi trương thanh hùng https://ebudezain.com/

hùng ebudezain

hùng đẹp trai

hùng thông minh lắm

public function render($request, Exception $e)
{
    if ($e instanceof Tymon\JWTAuth\Exceptions\TokenExpiredException) {
        return response()->json(['token_expired'], $e->getStatusCode());
    } else if ($e instanceof Tymon\JWTAuth\Exceptions\TokenInvalidException) {
        return response()->json(['token_invalid'], $e->getStatusCode());
    }

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