Tiếp theo bài Xác thực và cấp quyền truy cập trong Angular, trong bài này chúng ta sẽ thực hành viết ứng dụng xác thực người dùng với JWT token (JWT được tạo bởi REST API trong bài Tạo JWT và xác thực quyền truy cập trong Django Rest Framework).

Trước hết chúng ta tiến hành cài đặt jwt-decode để decode token nhận được từ server sử dụng dòng lệnh sau:

Tiếp theo ta tiến hành viết lại shared/auth.service.ts như sau:

1. Hàm login()

Ta gửi POST request tới REST API http://127.0.0.1:8000/get-token/ (xem thêm tại bài Tạo JWT và xác thực quyền truy cập trong Django Rest Framework) để xác thực người dùng. Khi người dùng nhập đúng username và password thì server sẽ trả về token của người dùng (bao gồm refresh token và access token). Ta tiến hành decode token nhận được sử dụng jwt-decode rồi lưu 4 thông tin gồm access token, access token expire (thời hạn sử dụng của access token), refresh token và refresh token expire vào localStorage. Sau đó ta chuyển hướng người dùng đến Dashboard để AuthGuard thực hiện xác thực quyền truy cập dựa trên role của người dùng

2. Hàm Logout()

Khi user logout chúng ta sẽ thực hiện xóa các thông tin đã lưu trong localStorage và chuyển hướng người dùng đến trang Login như sau:

3. Hàm isAuthenticated()

Khi người dùng được chuyển hướng đến Dashboard (hoặc khi người dùng truy cập một path bất kỳ) AuthGuard sẽ sử dụng hàm isAuthenticated() để kiểm tra người dùng có quyền truy cập hay không.

Ta sử dụng hàm localStorage.getItem() để kiểm tra sự tồn tại của refresh token và kiểm tra xem refresh token có còn thời hạn sử dụng hay không. Nếu người dùng có refresh token trong thời hạn sử dụng tức là người dùng sẽ có quyền truy cập ứng dụng

4. Các hàm kiểm tra access token

Để đảm bảo access token của người dùng luôn còn thời gian sử dụng, ta viết hàm tokenChecking() để kiểm tra nếu thời hạn sử dụng của access token còn không quá 1 phút thì sẽ gửi POST request tới http://127.0.0.1:8000/refresh-token/ sử dụng refresh token để lấy access token mới.

Hàm tokenChecking() sẽ được khởi chạy khi ta bắt đầu khởi chạy ứng dụng và sau đó sẽ được chạy mỗi phút một lần để kiểm tra access token bằng cách sử dụng setInterval() như sau:

Tiếp theo, ta viết JWTInterceptorService để thêm header với thông tin về access token vào các request gửi đến server như sau:

Để đảm bảo WTInterceptorService có thể thêm thông tin vào các Http request, ta tiến hành cấu hình provider trong app.module.ts như sau:

Trong bài Tạo JWT và xác thực quyền truy cập trong Django Rest Framework, ta đã viết REST API http://127.0.0.1:8000/stockApp/getInfo/ cho phép người dùng (đã được xác thực) truy cập thông tin về các mã chứng khoán. Do đó, trong bài này để kiểm tra hoạt động của Inceptor ta tạo thêm StockInfoComponent để hiển thị dữ liệu nhận được từ getInfo API như sau:

Khởi chạy ứng dụng với lệnh ng serve và đăng nhập ứng dụng tại http://localhost:4200/login; Click vào Stock Info ta được kết quả hiển thị dữ liệu chứng khoán như sau:Mở một tab mới và truy cập http://localhost:4200/dashboard/contact, ứng dụng cho phép ta truy cập Contact component vì access token với quyền Admin đã được lưu trong localStorage:Click Logout và truy cập lại địa chỉ http://localhost:4200/dashboard, ứng dụng chuyển hướng người dùng đến trang Login vì thông tin về token đã bị xóa khi người dùng Logout. Do đó, ứng dụng yêu cầu người dùng phải thực hiện đăng nhập lại.

Lưu ý: Khi gửi request tới Django server mà gặp lỗi “Access to XMLHttpRequest at ‘url’’ from origin has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource”: chúng ta tiến hành cài đặt django-cors-headers bằng lệnh pip install django-cors-headers và thực hiện cấu hình file settings.py của Django project như sau:

Với ALLOWED_HOSTS ta có thể sử dụng một trong hai cách sau:

Hoặc

Như vậy, với việc kết hợp sử dụng JWT được tạo bởi REST API trong bài Tạo JWT và xác thực quyền truy cập trong Django Rest Framework, chúng ta đã hoàn thành việc viết ứng dụng xác thực người dùng với JWT token. Các bạn có thể tham khảo toàn bộ code của bài này trong trang Github của Itech Seeker tại đây.

Tháng Chín 1, 2021
ITechSeeker