12/08/2018, 17:11

Wemos authenticate qua laravel (phần 4.4 - Server kết nối với Wemos)

Xin chào các bạn! Bài trước mình đã giới thiệu với các bạn cách tạo gửi request GET và POST trong wemos. Hôm nay chúng ta sẽ cùng xây dựng chức năng đăng nhập vào server laravel và kết nối socket.io sử dụng jwt để xác thực cho wemos nhé. Xem lại sơ đồ cho đỡ quên nào: Mình sẽ nói lại các bước ...

Xin chào các bạn! Bài trước mình đã giới thiệu với các bạn cách tạo gửi request GET và POST trong wemos. Hôm nay chúng ta sẽ cùng xây dựng chức năng đăng nhập vào server laravel và kết nối socket.io sử dụng jwt để xác thực cho wemos nhé.

Xem lại sơ đồ cho đỡ quên nào:

Mình sẽ nói lại các bước hoạt động để các bạn dễ hình dung nhé:

  • Gửi request đăng nhập vào server laravel và nhận được jwt-token
  • Kết nối với socket.io
  • On event thay đổi trạng thái của đèn. Khi có event thì thay đổi trạng thái tương ứng.
  • Emit trạng thái hiện tại của đèn

Ở phần Kết nối với socket.io do có bước xác thực người dùng nên luồng kết nối sẽ như sau:

  • Thiết lập bắt tay
  • Thực hiện authenticate sử dụng jwt-token đã nhận được
  • Chuyển đổi giao thức từ HTTP thành Web socket

Chúng ta sẽ sử dụng chương trình server đã tạo từ bài trước.

Các bạn hãy cài đặt như project laravel bình thường sau đó chạy lệnh php artisan migrate --seed để tạo dữ liệu test nhé.

Sửa lại device models

Muốn thư viện tymon/jwt-auth có thể hoạt động với Device model ta cần phải implements JWTSubject cho Device model. Và phải thêm 2 hàm phục vụ chức năng lấy các trường để tạo auth-token.

// appModelsDevice.php
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        // Khi nodejs nhận được chuỗi jwt và parse ra sẽ được dữ liệu trả về trong hàm này
        return [
            'id' => $this->id,
            'identify_code' => $this->identify_code,
            'guard' => 'device',
        ];
    }

Tạo route

Route đăng nhập, đăng xuất sẽ như sau:

Route::group(['prefix' => 'device', 'namespace' => 'Device'], function () {
    Route::get('session', 'SessionController@session');
    Route::post('login', 'SessionController@login');
    Route::post('logout', 'SessionController@logout');
});

Tạo controller đăng nhập

Tạo controller AppHttpControllersDeviceSessionController.

Ta cần phải tạo 3 hàm tương ứng với 3 chức năng:

  • Kiểm tra trạng thái đăng nhập (Hàm session)
  • Đăng nhập (Hàm login)
  • Đăng xuất (Hàm logout)

Dữ liệu trả về có các status sau:

  • login_in: Đã đăng nhập thành công vào hệ thống
  • not_login: Chưa đăng nhập
  • login_fail: Đăng nhập thất bại
  • logout_success: Đăng xuất thành công
const RESPON_STATUS = [
        'not_login' => 0,
        'login_in' => 1,
        'login_fail' => 2,
        'logout_success' => 3,
    ];

Hàm get session

Trả về dữ liệu đã login thành công hoặc là chưa login

    public function session(JWTAuth $auth)
    {
        if (Auth::guard($this->guard)->check()) {
            return $this->userWasAuthenticated($auth);
        }

        return $this->sessionResponse(self::RESPON_STATUS['not_login']);
    }

Dữ liệu trả về khi đã login

    protected function userWasAuthenticated($auth)
    {
        $user = Auth::guard($this->guard)->user();
        if ($user->isActive()) {
            // Lấy auth token từ user đã đăng nhập
            $authToken = $auth->fromUser($user);
            $result = $this->makeUserResult($user, $authToken);

            return $this->sessionResponse(self::RESPON_STATUS['login_in'], $result);
        }

        $this->logout();
        return $this->sessionResponse(self::RESPON_STATUS['login_fail']);
    }

Hàm login

Giúp device đăng nhập vào hệ thống

    public function login(Request $request, JWTAuth $auth)
    {
        $this->validateLogin($request);
        $credentials = $request->only('identify_code', 'password');

        if ($this->attemptLogin($request, $credentials)) {
            return $this->userWasAuthenticated($auth);
        }

        return $this->sessionResponse(self::RESPON_STATUS['login_fail']);
    }

Hàm logout

Hàm đăng xuất

    public function logout()
    {
        Auth::guard($this->guard)->logout();

        return $this->sessionResponse(self::RESPON_STATUS['logout_success']);
    }

Hàm sessionResponse

Trả về dữ liệu với token để Device có thể sử dụng cho việc gửi post request.

    protected function sessionResponse($status, $data = [], $statusCode = 200)
    {
        $data['status'] = $status;
        $data['token'] = csrf_token();
        return response()->json($data, $statusCode);
    }

Phần này khá đơn giản. Các bạn có thể đọc code full tại đây.

Bây giờ chỉ còn việc viết chương trình cho wemos thôi. Bắt đầu thực hiện từng bước một nào!

Chúng ta sẽ sử dụng thư viện esp8266-socket.io này để kết nối socket. Các bạn tải hoặc clone thư viện này về xong coppy vào thư mục /home/{user}/Arduino/libraries là có thể sử dụng được rồi.

Viết hàm gửi request và lưu cookies lại

Đầu tiên chúng ta cần phải biết một điều là Laravel sẽ giữ session đăng nhập bằng cookies. Nếu không lưu lại thì request sau bạn gửi sẽ thành session khác. Và tất nhiên khi mà bạn đăng nhập ở request trước rồi, request sau server vẫn coi là chưa đăng nhập nếu bạn không gửi cookies kèm theo.             </div>
            
            <div class=

0