Tại sao phải sử dụng JSON Web Token (JWT) để bảo mật API
Giới thiệu Trước khi tìm hiểu bài này , các bạn hãy xem qua bài viết JWT là gì ? trước đó mình có chia sẻ nhé. Như chúng ta đã biết trong API thì Client giao tiếp và gửi request (yêu cầu) đến Server thông qua URL trên giao thức HTTP , ví dụ ta có 2 yêu cầu // [GET] ...
Giới thiệu
Trước khi tìm hiểu bài này , các bạn hãy xem qua bài viết JWT là gì ? trước đó mình có chia sẻ nhé.
Như chúng ta đã biết trong API thì Client giao tiếp và gửi request (yêu cầu) đến Server thông qua URL trên giao thức HTTP , ví dụ ta có 2 yêu cầu
// [GET] @RequestMapping(value = "/users/{userid}", method = RequestMethod.GET) public User findUserByUserId(@PathVariable("userid") long userId) { return userRepository.findOne(userId); } // [DELETE] @RequestMapping(value = "/users/{userid}", method = RequestMethod.DELETE) public String deleteUserByUserId(@PathVariable("userid") long userId) { userRepository.delete(userId); return "Successful"; }
- @RequestMapping : dùng để cấu hình URL của request
- method : ở đây mình sử dụng 2 phương thức đó là GET và DELETE
- @PathVariable: đây là tham số truyền vào đi kèm với request , ở đây mình truyền trực tiếp trên đường dẫn nên mình sử dụng PathVariable
Ví dụ ta yêu cầu Server lấy User có Id là 01 như sau [GET] localhost:8080/users/01 hoặc xóa [DELETE] localhost:8080/users/01. Ở đây nếu chúng ta không sử dụng bất kì phương thức nào để bảo mật API thì tất cả các User khác điều có thể gọi tới các Request này để lấy thông tin hoặc xoá User 01 và Server sẽ thực hiện yêu cầu mà không cần biết yêu cầu này có phải là của User 01 hay không . Điều này rất nguy hiểm , các hacker có thể xóa hết dữ liệu hoặc đánh cắp thông tin người dùng bằng cách truy cập vào các URL này , cho nên ta cần một phương pháp nào đó để Server xác định được yêu cầu đó là của User01 thì Server mới thực hiện , vì vậy ta sẽ sử dụng JWT
Cách thức hoạt động của JWT
Giải thích theo sơ đồ trên thì :
- Bước 1 : Người dùng yêu cầu đăng nhập với Username , Password
- Bước 2 + 3 : Server nhận được yêu cầu và kiểm tra Username , Password nếu đúng sẽ gửi cho người dùng một chuỗi JWT
- Bước 4 : Người dùng sẽ dùng JWT này kèm theo các yêu cầu kế tiếp
- Bước 5 + 6 : Server sẽ nhận yêu cầu và kiểm tra chuổi JWT , nếu chuỗi hợp lệ thì sẽ thực hiện yêu cầu
Hơi rối một chút đúng không , mình sẽ giải thích theo ví dụ ở đầu bài thì ta sẽ có :
- Bước 1 : User01 sẽ yêu cầu đăng nhập với Username và Password của mình
- Bước 2 + 3 : Server nhận được yêu cầu của User01 và kiểm tra Username , Password nếu đúng sẽ gửi về User01 một chuỗi JWT
- Bước 4 : Lúc này User01 yêu cầu [GET] localhost:8080/users/01 kèm theo chuỗi JWT vừa nhận được
- Bước 5 + 6 : Server nhận yêu cầu và kiểm tra xem nếu JWT chính xác là chuổi JWT lúc đầu Server đã gửi cho User01 thì sẽ trả về các thông tin của User01
Nếu vẫn chưa hiểu mời các bạn theo dõi tiếp sau đây mình sẽ ví dụ thực tế sơ đồ trên , mình sử dụng phần mềm PostMan để request Server
Login
Chúng ta sẽ yêu cầu đăng nhập với username = user , password = user (Tài khoản này có Id = 88) Khi đăng nhập thành công thì Server sẽ trả về một chuỗi access_token như trên (các trường khác như scope , jti , token_type mình sẽ nói sau nhé bài này mình chỉ đi sâu vào cách thức hoạt động của nó thôi) . Nếu bạn nào thắc mắc chuổi này được tạo ra như thế nào thì xem lại bài viết trước của mình nhé
// access_token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidGVzdGp3dHJlc291cmNlaWQiXSwidXNlcl9uYW1lIjoidXNlciIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJleHAiOjE1MTM4MzE3ODcsImF1dGhvcml0aWVzIjpbIlNUQU5EQVJEX1VTRVIiXSwianRpIjoiYzBiNjE0NDgtZWQyMi00OTMxLThkZGQtZDkyZTI1ZWE1OTU1IiwiY2xpZW50X2lkIjoiY2xpZW50aWQifQ.2IraSC0vG7iT98NqdtJ4YMAOh7wXnHcLq2hCstTYxN8
Request
Sau khi nhận được Token rồi chúng ta sẽ gửi yêu cầu Server lấy thông tin của User này kèm theo Token được đóng gói ở Header , đây là kết quả
Ở trên là tất cả thông tin của UserId = 88 mình vừa đăng nhập , mình thử sử dụng tiếp Token này yêu cầu Server lấy thông tin của UserId = 87 xem sao
Server sẽ từ chối yêu cầu ngay vì Token bạn gửi không có quyền để truy cập tới dữ liệu của UserId = 87 Như vậy bạn đã hiểu được cách thức hoạt động của JWT để bảo mật API là như thế nào rồi đúng không , cách này giúp chúng ta giải quyết được các vấn đề đã được đề cập ở phần giới thiệu . Server sẽ biết chính xác được đối tượng gửi Request và thực hiện yêu cầu.
Lưu ý : Một chuỗi Token khi sinh ra không thể tồn tại mãi được vì như vậy nếu sau này hacker lấy được chuỗi Token thì sẽ lấy được tất cả quyền truy cập của bạn , cho nên chúng ta phải thiết lập thêm phương thức hủy Token đi và Create Token mới khi người dùng đăng nhập lần sau. Thường thì một Token nên có thời hạn từ 10 đến 30 ngày hoặc khi người dùng Logout thì Token sẽ bị hủy ngay . Như các bạn thấy nếu bên Website thì Token này sẽ được lưu vào file Cookie của trình duyệt , nếu bạn xóa đi Cookie thì tất cả các tài khoản mà bạn đăng nhập lần trước sẽ không được lưu lại nữa và bạn phải nhập lại mật khẩu và nhận được một Token mới
Tài liệu
https://medium.com/@nydiarra/secure-a-spring-boot-rest-api-with-json-web-token-reference-to-angular-integration-e57a25806c50