36 điểm bởi GN⁺ 2024-05-28 | 8 bình luận | Chia sẻ qua WhatsApp
  • JWT là viết tắt của JSON Web Tokens, một tiêu chuẩn dành cho token đã được xác thực.
  • JWT bao gồm header, payload, chữ ký hoặc mã xác thực thông điệp.
  • Bất kỳ ai có khóa xác minh đều có thể kiểm tra tính xác thực của payload.

Mẫu sử dụng JWT phổ biến

  • JWT chứa thông tin như bên phát hành, bên nhận, chủ thể và thời gian hết hạn.
  • Sau khi xác minh tính xác thực của token, bên nhận sẽ kiểm tra xem token đã hết hạn hay chưa và coi chủ thể là người dùng đã được xác thực.

Ưu điểm của JWT

  • Ưu điểm lớn nhất của JWT là bên nhận có thể xác minh tính xác thực của token mà không cần kết nối tới cơ sở dữ liệu người dùng.
  • Trong môi trường triển khai quy mô lớn, dịch vụ xác thực có thể là dịch vụ duy nhất truy cập cơ sở dữ liệu người dùng trung tâm.

Vấn đề đăng xuất và vô hiệu hóa phiên

  • Thời hạn sống của token xác thực nên ngắn, ví dụ tối đa 5 phút.
  • Client cũng sẽ được cấp refresh token để có thể yêu cầu token xác thực mới.
  • Refresh token thực chất đóng vai trò là token phiên.

Khi không cần JWT

  • Để triển khai đăng xuất, cần duy trì danh sách cho phép các JWT hợp lệ hoặc danh sách từ chối các JWT đã bị thu hồi.
  • Để chặn người dùng, cần kiểm tra cờ "người dùng đang hoạt động" trong cơ sở dữ liệu.
  • Cần thêm các quan hệ bổ sung giữa đối tượng người dùng và các đối tượng khác.
  • Thực hiện các tác vụ liên quan đến cơ sở dữ liệu.

Kết luận

  • Nếu chỉ cần một trong các điều kiện trên, thì không cần JWT.
  • Tốt hơn nên dùng token phiên dạng opaque thông thường và lưu trong cơ sở dữ liệu.
  • Có thể tránh được các nhược điểm của JWT và giảm độ phức tạp.

Ý kiến của GN⁺

  • JWT phù hợp với các dịch vụ quy mô lớn, nhưng với hầu hết dịch vụ nhỏ thì có thể tạo ra độ phức tạp quá mức.
  • Cơ chế quản lý phiên thông thường là đủ cho phần lớn ứng dụng web.
  • Khi dùng JWT, có thể gặp khó khăn khi triển khai các tính năng như đăng xuất và vô hiệu hóa phiên.
  • Để tận dụng ưu điểm của JWT, cần cân nhắc kỹ quy mô và yêu cầu của dịch vụ.
  • Một lựa chọn thay thế khác là xem xét các framework xác thực như OAuth2.

8 bình luận

 
dhlee0305 2024-05-30

Khi cần nhiều hình thức xác thực phía client, việc dùng JWT mang lại khá nhiều lợi ích.
Tuy vậy, vì khả năng mở rộng và bảo mật luôn hướng đến những mục tiêu khác nhau, nên nếu bảo mật đặc biệt quan trọng thì tôi nghĩ sẽ tốt hơn nếu dùng phương pháp khác.

 
koxel 2024-05-28

Cá nhân tôi cho rằng token jwt chỉ nên dùng khi trao đổi giữa các hệ thống qua trình duyệt những dữ liệu tạm thời mà dù bị lộ cũng không sao.
Còn với token dùng để xác thực có chứa thông tin cá nhân thì tôi thấy dùng token opaque sẽ tốt hơn..

 
namarie32ilu 2024-05-28

Theo kinh nghiệm cá nhân của tôi, khi làm MVP thì JWT có những lợi ích nhất định.

Ví dụ, nếu là một dịch vụ do một mình xây dựng và vận hành, tôi nghĩ nó giúp giảm chi phí lên kế hoạch phát sinh từ các yêu cầu đột ngột. Dù sao thì mối quan hệ dữ liệu được thiết lập ban đầu sau một hai tháng thường thay đổi hoàn toàn, nên trong trạng thái yêu cầu chưa được xác định rõ ràng, ít nhất là với phần liên quan đến auth, nếu cấu hình payload JWT theo dạng các trường tùy chọn rồi triển khai tính năng trước, thì ngay cả khi bộ phận kế hoạch chưa làm việc tách domain và tách dịch vụ, vẫn có thể trước hết triển khai theo hướng dễ tách riêng từng domain trong một dịch vụ monolithic để thử nghiệm thị trường. (Sau đó mới tiến hành các bước tách dịch vụ về sau. Hoặc bỏ đi nếu không cần.)

Tuy vậy, có lẽ điều này cũng khác nhau tùy theo domain của dịch vụ muốn xây dựng. Dự án đó là một dự án có mức độ tích hợp cao với bên thứ ba ngay cả trong nhóm dịch vụ thời gian thực, nên tôi nhớ đã tiến hành với suy nghĩ rằng nếu cứ triển khai nhanh thì khi một lượng rất lớn document/row tích tụ trong DB, chi phí quản lý có thể sẽ tăng lên đáng kể.

Dĩ nhiên, nếu mục tiêu là tập trung làm thật nhanh thì tôi cho rằng phương thức session sẽ tốt hơn. (Ở giai đoạn đầu, coupling giữa nhiều dịch vụ chưa mạnh nên cũng dễ đập đi làm lại.) Chi phí bàn giao khi có thành viên từ team khác tham gia cũng thấp hơn.

Khi đó tôi cũng từng suy nghĩ khá nhiều theo hướng này hướng kia, nhưng thật ra nhìn lại bây giờ thì dù triển khai theo cách nào, có lẽ mức độ ảnh hưởng tới dự án cũng sẽ không quá nghiêm trọng.

 
superwoou 2024-05-28

Cá nhân tôi nghĩ rằng khi dùng API gateway, việc triển khai auth bằng JWT sẽ mang lại lợi ích. Nhưng tôi tò mò không biết ở các dịch vụ quy mô nhỏ thì JWT có những ưu điểm gì. Có phải bạn đang nói đến các trường hợp mà thông tin người dùng được chứa trong JWT thay đổi thường xuyên không?

 
namarie32ilu 2024-05-30

Về tổng thể thì khá giống với điều bạn nói. Chỉ là thay vì phải thường xuyên thay đổi thông tin do bản thân mô hình người dùng thay đổi, tình huống của tôi gần hơn với việc bổ sung tùy chọn khi thêm tính năng mới hoặc khi một dịch vụ mới cần thông tin bổ sung để dùng công cụ bên thứ ba. (Nói thêm một chút thì khi đó cũng đang ở trong một tình huống khá lưng chừng: có nên tách riêng đơn vị quản lý auth bằng thứ như API gateway hay không, hoặc liệu có một server đảm nhiệm vai trò tương tự hay không...)

Lấy ví dụ cụ thể hơn thì khi đó chúng tôi đang lấy dịch vụ A làm chính. Vì vẫn là giai đoạn MVP nên trong bảng người dùng chỉ giữ thông tin thanh toán và việc người dùng đã được xác thực hay chưa. Nhưng rồi có yêu cầu thêm hai dịch vụ B và C, là những dịch vụ chỉ dùng được khi mỗi người dùng có thông tin xác thực khác nhau. Trong số đó, B còn chưa quyết định có được đưa vào trong dịch vụ A hay không, còn C thì thậm chí có thể bị bỏ đi nên họ muốn thử nhẹ trước. (Còn tính năng quản lý plan thì dù không nói ra, rõ ràng cũng phải thêm vào để tránh phát sinh vấn đề). Ngoài ra, họ còn muốn bắt đầu theo kiểu dùng thử luôn B và C ngay trên trang web vốn đang cung cấp dịch vụ A. Do đặc thù của dịch vụ đang vận hành, trước khi tạo bảng quản lý plan (hoặc một bảng xác thực mang tính tổng quát) rồi vẽ quan hệ domain theo từng dịch vụ và mapping để triển khai, thì việc truy vấn nhiều bảng (hoặc nhiều collection) là điều gần như không tránh khỏi. Nếu đây là dự án có người đứng ra dọn bài bản thì đáng lẽ chúng tôi đã họp vài lần để chốt thật sắc xem rốt cuộc vấn đề cần giải quyết là gì và tính năng mong muốn chính xác là gì, nhưng khi đó không có gì bảo đảm được điều đó. Hơn nữa, cũng không rõ đến bao giờ mới có thể dọn được những khoản nợ kỹ thuật này. Vì thế, kiểu chuyện như vậy đã có dấu hiệu từ trước cả khi dịch vụ A ra mắt... nên ở cấu hình ban đầu, khi nghĩ rằng lúc auth nên đi theo hướng tiết kiệm tối đa chi phí truy vấn và chi phí quản lý về sau, tôi đã chọn JWT. Ngoài ra cũng có rất nhiều chuyện lặt vặt tương tự như vậy.

Tuy nhiên, như tôi đã nói ở cuối bình luận, thật ra dù triển khai bằng cách gì thì có lẽ nó cũng không tạo ảnh hưởng quá lớn đến bản thân dự án. Nếu làm bằng session thì chắc cũng sẽ tìm ra cách xoay xở theo kiểu của session. Ngược lại, có lẽ việc lập trình viên liên tục rơi vào tình huống phải làm việc của vị trí khác hoặc phải thường xuyên chịu chi phí giao tiếp bị đổ vỡ mới là thứ chí mạng hơn nhiều.

 
a1eng0 2024-05-28
  • Trường hợp có thể tận dụng JWT là khá hiếm; trong đa số tình huống, cách dùng session truyền thống phù hợp hơn.
  • Nhiều lập trình viên hiểu sai bản chất của JWT hơn bạn nghĩ, và bỏ qua nhiều nhược điểm rồi trao đổi với nhau kiểu “nghe nói dùng cái này thì ít phải dùng DB hơn, hiệu năng nhanh hơn”.
  • Một khi đã bị cuốn vào kiểu trao đổi đó, bạn sẽ phải bắt đầu giải thích từ bản chất của xác thực bằng khóa công khai và chữ ký điện tử, và điều đó cực kỳ đau đầu.
  • JWT vốn không phải là đối tượng cần cân nhắc, nhưng tôi đã nhiều lần trải qua việc nó như một hố đen, cứ kéo các cuộc họp sang một hướng kỳ quặc.
 
newro 2024-05-30

Dù phù hợp với kiến trúc monolith, khi bắt đầu tách một phần dịch vụ ra hoặc đứng trước ngã rẽ mở rộng, JWT và logic dựa trên session rõ ràng cho thấy sự khác biệt. Không chỉ ở quy trình xác thực đơn thuần, mà ngay cả về tính tiện dụng trong logic nội bộ, cách xử lý nguồn gốc dữ liệu cũng sẽ khác đi, nên tôi không rõ phải dựa trên tiêu chí nào để đánh giá rằng bối cảnh “dịch vụ nhỏ” là phù hợp. Có phải giả định rằng mọi dịch vụ chắc chắn sẽ luôn nhỏ? Hay là giả định rằng với dịch vụ lớn thì sẽ không dễ áp dụng? Tuy vậy, tôi vẫn nghĩ rằng dịch vụ chúng ta tạo ra nên tối thiểu có một cấu trúc có thể hỗ trợ những bối cảnh hữu ích, dù chưa biết sẽ gặp tình huống nào. Tiền đề của “dịch vụ nhỏ” dường như chỉ dẫn đến việc nó sẽ mãi nhỏ mà thôi.

 
GN⁺ 2024-05-28
Ý kiến trên Hacker News

Tóm tắt bình luận trên Hacker News

  • Khuyến nghị dùng cơ chế session truyền thống: Nên sử dụng cơ chế session thông thường do framework web cung cấp. JWT không cần thiết trong mọi trường hợp.
  • Sử dụng JWT trong kiến trúc microservices: Trong môi trường microservices, JWT rất hữu ích. Với một ứng dụng web nguyên khối duy nhất, nhu cầu dùng JWT thấp hơn.
  • Vấn đề bảo mật của JWT: JWT có thể dễ gặp lỗ hổng bảo mật, nhưng nguyên nhân là do dùng sai thư viện hoặc cấu hình không đúng. Nếu dùng thư viện đáng tin cậy thì không có vấn đề gì.
  • Kinh nghiệm dùng JWT: Có kinh nghiệm giải quyết vấn đề bằng JWT và không hối tiếc.
  • Sử dụng AWS Cognito: Nếu xử lý xác thực bằng AWS Cognito thì có thể dễ dàng triển khai MFA, đăng nhập mạng xã hội, xác thực email, v.v. Nhược điểm của JWT có thể được xử lý bằng thời gian sống ngắn và làm mới thường xuyên.
  • JWT và dịch vụ bên ngoài: JWT thường được dùng trong các dịch vụ bên ngoài. Dùng JWT giúp lập trình viên chỉ cần hiểu một khái niệm duy nhất.
  • Dùng JWT cả trong môi trường nhỏ: Ngay cả trong môi trường nhỏ, JWT cũng có thể hữu ích. Có thể hạn chế quyền truy cập vào dữ liệu nhạy cảm và giảm chi phí.
  • So sánh JWT và session token: Nhiều triển khai JWT trong thực tế đổi JWT lấy session token. JWT hữu ích để IDP xác minh danh tính người dùng.
  • Ưu điểm của JWT: Có thể chuẩn hóa hệ thống xác thực thông qua OAuth 2 và OIDC, đồng thời xử lý xác thực frontend và API theo cùng một cách.
  • Sự tiện lợi khi dùng JWT: Trong các môi trường như Azure, dùng JWT cho phép truy cập nhiều API mà không cần lo về trạng thái session.
  • Dùng JWT trong xác thực giữa máy với máy: Trong xác thực machine-to-machine, JWT là lựa chọn phù hợp nhất. Ví dụ, trong giao tiếp giữa các Raspberry Pi, JWT được dùng để xử lý xác thực và phân quyền.