Xác thực: Sử dụng JWT so với phiên


122

Lợi thế của việc sử dụng JWT so với các phiên trong các tình huống như xác thực là gì?

Nó được sử dụng như một cách tiếp cận độc lập hay nó được sử dụng trong phiên?

Câu trả lời:


212

JWT không mang lại lợi ích gì khi sử dụng "phiên". JWT cung cấp phương tiện duy trì trạng thái phiên trên máy khách thay vì thực hiện trên máy chủ.

Ý mọi người thường nói khi hỏi điều này là "Lợi ích của việc sử dụng JWT so với việc sử dụng phiên phía máy chủ "

Với các phiên phía máy chủ, bạn sẽ phải lưu trữ mã định danh phiên trong cơ sở dữ liệu, hoặc nếu không thì giữ nó trong bộ nhớ và đảm bảo rằng máy khách luôn truy cập vào cùng một máy chủ. Cả hai điều này đều có nhược điểm. Trong trường hợp của cơ sở dữ liệu (hoặc bộ lưu trữ tập trung khác), điều này sẽ trở thành một nút thắt cổ chai và một điều cần duy trì - về cơ bản là một truy vấn bổ sung được thực hiện với mọi yêu cầu.

Với giải pháp trong bộ nhớ, bạn giới hạn tỷ lệ theo chiều ngang của mình và các phiên sẽ bị ảnh hưởng bởi sự cố mạng (máy khách chuyển vùng giữa Wi-Fi và dữ liệu di động, máy chủ khởi động lại, v.v.)

Di chuyển phiên sang máy khách có nghĩa là bạn loại bỏ sự phụ thuộc vào phiên phía máy chủ, nhưng nó đặt ra một loạt thách thức riêng.

  • Lưu trữ mã thông báo an toàn
  • vận chuyển nó một cách an toàn
  • Các phiên JWT đôi khi có thể khó làm mất hiệu lực.
  • Tin tưởng vào yêu cầu của khách hàng.

Các vấn đề này được chia sẻ bởi JWT và các cơ chế phiên phía máy khách khác.

JWT đặc biệt giải quyết vấn đề cuối cùng trong số này. Có thể hữu ích để hiểu JWT là gì:

Đó là một chút thông tin. Đối với phiên người dùng, bạn có thể bao gồm tên người dùng và thời gian mã thông báo hết hạn. Nhưng có thể hình dung nó là bất kỳ thứ gì, ngay cả ID phiên hoặc toàn bộ hồ sơ của người dùng. (Xin đừng làm vậy) Nó có một chữ ký an toàn để ngăn các bên độc hại tạo ra các mã giả mạo (Bạn cần truy cập vào khóa riêng của máy chủ để ký chúng và bạn có thể xác minh rằng chúng không bị sửa đổi sau khi chúng được ký) Bạn gửi chúng với mọi yêu cầu, giống như cookie hoặc AuthorizationHeader sẽ được gửi. Trên thực tế, chúng thường được gửi trong Authorizationtiêu đề HTTP nhưng sử dụng cookie cũng tốt.

Mã thông báo đã được ký và do đó máy chủ có thể xác minh nguồn gốc của nó. Chúng tôi sẽ giả định rằng máy chủ tin tưởng vào khả năng ký an toàn của chính nó (bạn nên sử dụng thư viện tiêu chuẩn: không cố gắng tự làm và bảo mật máy chủ đúng cách)

Về vấn đề vận chuyển mã thông báo một cách an toàn, câu trả lời thường là gửi nó qua một kênh mã hóa, thường là httpS.

Về việc lưu trữ an toàn mã thông báo trong máy khách, bạn cần đảm bảo rằng kẻ xấu không thể lấy được nó. Điều này (hầu hết) có nghĩa là ngăn JS từ các trang web xấu đọc mã thông báo để gửi lại cho họ. Điều này được giảm thiểu bằng cách sử dụng các chiến lược tương tự được sử dụng để giảm thiểu các loại tấn công XSS khác.

Nếu bạn có nhu cầu hủy bỏ JWT, chắc chắn có nhiều cách để đạt được điều này. Lưu trữ kỷ nguyên trên mỗi người dùng chỉ dành cho những người dùng đã yêu cầu chấm dứt "các phiên khác" của họ là một phương pháp rất hiệu quả và có lẽ sẽ đủ tốt. Nếu một ứng dụng cần hủy hiệu lực mỗi phiên, thì ID phiên có thể được duy trì theo cách tương tự và bảng "mã thông báo bị giết" vẫn có thể được duy trì để nhỏ hơn nhiều so với bảng người dùng đầy đủ (Bạn chỉ cần giữ lại các bản ghi mới hơn bảng thời gian tồn tại của mã thông báo được phép lâu nhất.) Vì vậy, khả năng làm mất hiệu lực mã thông báo phủ nhận một phần lợi ích của các phiên phía máy khách mà bạn sẽ phải duy trì trạng thái đã kết thúc phiên này. Đây nhiều khả năng sẽ là một bảng nhỏ hơn nhiều so với bảng trạng thái phiên ban đầu, do đó, việc tra cứu vẫn hiệu quả hơn.

Một lợi ích khác của việc sử dụng mã thông báo JWT là nó rất dễ triển khai bằng cách sử dụng các thư viện có sẵn ở mọi ngôn ngữ mà bạn có thể mong đợi có nó. Nó cũng hoàn toàn tách rời khỏi sơ đồ xác thực người dùng ban đầu của bạn - nếu bạn chuyển sang hệ thống dựa trên dấu tay, bạn không cần thực hiện bất kỳ thay đổi nào đối với sơ đồ quản lý phiên.

Một lợi ích tinh tế hơn: Bởi vì JWT có thể mang "thông tin" và điều này có thể được khách hàng truy cập, bạn có thể bắt đầu thực hiện một số việc thông minh. Ví dụ: nhắc người dùng rằng phiên của họ sẽ hết hạn vài ngày trước khi họ đăng xuất, cung cấp cho họ tùy chọn xác thực lại, dựa trên ngày hết hạn trong mã thông báo. Bất cứ điều gì bạn có thể tưởng tượng.

Tóm lại: JWTs giải đáp một số thắc mắc và thiếu sót của các kỹ thuật phiên khác.

  1. Xác thực "rẻ hơn" bởi vì bạn có thể loại bỏ một chuyến đi khứ hồi của DB (hoặc ít nhất là có một bảng nhỏ hơn nhiều để truy vấn!), Từ đó cho phép khả năng mở rộng theo chiều ngang.
  2. Tuyên bố từ phía khách hàng chống giả mạo.

Mặc dù JWT không trả lời các vấn đề khác như lưu trữ hoặc truyền tải an toàn, nhưng nó không đưa ra bất kỳ vấn đề bảo mật mới nào.

Có rất nhiều tiêu cực tồn tại xung quanh JWT nhưng nếu bạn triển khai bảo mật tương tự như bạn làm cho các loại xác thực khác, bạn sẽ ổn.

Một lưu ý cuối cùng: Nó cũng không phải là Cookies vs Tokens. Cookie là một cơ chế lưu trữ và vận chuyển các bit thông tin và cũng có thể được sử dụng để lưu trữ và vận chuyển các mã thông báo JWT.


4
Cần lưu ý rằng các phiên phía máy chủ cũng không phải lưu trữ bất kỳ thông tin nào trên máy chủ. Máy chủ có thể sử dụng máy khách làm cửa hàng theo cách giống như JWT. Sự khác biệt thực sự là ở chỗ 1) tránh các quy tắc bảo mật của trình duyệt bằng cách chuyển giá trị dưới dạng tiêu đề yêu cầu khác với tiêu đề cookie và 2) có định dạng chuẩn hóa với JWT.
Xeoncross

1
Bạn có nói rằng có an toàn khi lưu trữ một jwt trong bộ nhớ cục bộ không? Nếu không, đâu là nơi an toàn để lưu nó để người dùng vẫn đăng nhập?
Jessica

1
Có localstorage thường là nơi chính xác nhất để lưu trữ phía máy khách. Bạn cần phải đối phó với XSS - Tôi không phải là chuyên gia lập trình web nhưng hãy xem Câu trả lời này stackoverflow.com/a/40376819/1810447 và tìm kiếm "Cách bảo vệ chống lại XSS"
The Tahaan 28/09/19

1
Trong nhận xét của bạn, bạn không nói về giải pháp dựa trên bộ nhớ cache + mã thông báo phiên. Đối với tôi, nó có vẻ "tốt hơn" so với bảng JWT + "mã thông báo bị giết", bởi vì với bảng "mã thông báo bị giết" này, dù sao thì bạn cũng cần có quyền truy cập DB, mà bạn cũng sẽ có với phiên + bộ nhớ cache (điều đó cũng nhỏ). Và kiên trì JWT khó triển khai hơn các phiên liên tục, vì bạn cần chơi với refresh_token (nên duy trì hai mã thông báo) ... Mọi nhận xét sẽ thực sự được đánh giá cao ... đặc biệt nếu bạn có một số con số để chỉ cách JWT + kill_table hiệu quả hơn session + cache ;-)
tobiasBora

2
@TheTahaan localStorage không được khuyến nghị để lưu trữ JWT. Liên kết mà bạn đã chia sẻ cũng đề cập đến điều đó. Đây diễn đàn có lời giải thích tốt là tại sao JWT không nên được lưu trữ trong localStorage.
Harke

40

Câu trả lời ngắn gọn là: Không.

Một phiên bản dài hơn là:

Tôi đã triển khai JWT để quản lý phiên sau khi đọc đề xuất này trong tài liệu GraphQL :

Nếu bạn không quen thuộc với bất kỳ cơ chế xác thực nào trong số này, chúng tôi khuyên bạn nên sử dụng express-jwt vì nó đơn giản mà không ảnh hưởng đến tính linh hoạt trong tương lai.

Việc thực hiện thực sự đơn giản vì nó chỉ thêm một chút phức tạp. Tuy nhiên, sau một thời gian, tôi (cũng như bạn) bắt đầu tự hỏi lợi ích của nó là gì. Hóa ra là có rất ít (hoặc có thể không có) cho JWT trong chừng mực quản lý phiên, vì bài đăng trên blog này giải thích chi tiết:

Ngừng sử dụng JWT cho các phiên


0

Hai xu của tôi, trên đường đi thêm một số tương phản với bài đăng blog nổi tiếng của joepie91.

Xem xét rằng các ứng dụng ngày nay (và ngày mai) là (chủ yếu) trên nền tảng đám mây
Có một lợi ích kinh tế đối với Xác thực JWT không trạng thái , quy mô theo quy mô ứng dụng: Các
ứng dụng đám mây phải trả chi phí theo từng nhịp thở một .
Chi phí này được giảm xuống khi người dùng không còn phải xác thực "chống lại" một cửa hàng phiên.

Xử lý
Chạy một cửa hàng phiên 24/7 sẽ tốn tiền.
Bạn không thể thoát khỏi các giải pháp dựa trên bộ nhớ trong thế giới của K8S, vì các nhóm là phù du.
Các phiên cố định sẽ không hoạt động tốt vì cùng một lý do.

Lưu
trữ Lưu trữ dữ liệu tốn tiền. lưu trữ dữ liệu trong ổ SSD thậm chí còn tốn nhiều chi phí hơn.
Các hoạt động liên quan đến phiên cần được giải quyết nhanh chóng, vì vậy ổ đĩa quang không phải là một lựa chọn.

I / O
Một số nhà cung cấp dịch vụ đám mây tính phí I / O liên quan đến Đĩa.

Băng thông
Một số nhà cung cấp đám mây tính phí hoạt động mạng giữa các phiên bản máy chủ.
Điều này áp dụng vì gần như chắc chắn rằng API và cửa hàng phiên là các phiên bản riêng biệt.

Phân cụm cửa hàng phiên
Chi phí leo thang tất cả các chi phí đã nói ở trên hơn nữa.


"Bạn không thể thoát khỏi các giải pháp dựa trên bộ nhớ trong thế giới của K8S, vì các nhóm là phù du" Không chắc bạn muốn nói gì về điều này. Redis chắc chắn hoạt động trong môi trường K8S và một redis pod thường xuyên bị lỗi đủ để ảnh hưởng đến người dùng của bạn dường như rất khó xảy ra.
yên tĩnh Kiểm tra

@quietContest Cá nhân tôi không muốn đề cập đến khả năng xảy ra khi xây dựng phần mềm. BTW, giải pháp ổn định sang một bên, một cuộc tấn công có thể khiến phần mềm bị lỗi và nhóm khởi động lại - điều này sẽ dẫn đến mất phiên. Tôi chọn giải pháp dựa trên JWT vì lý do đó.
Eyal Perry

1
"Cá nhân tôi không thích đề cập đến khả năng xảy ra khi xây dựng phần mềm". Tôi nghĩ rằng tất cả chúng ta đều thích điều đó hơn, đó là lý do tại sao chúng ta không nên kiến ​​trúc các hệ thống dựa vào kho lưu trữ dữ liệu trong bộ nhớ không bao giờ bị lỗi, bởi vì khả năng xảy ra điều đó có vẻ khá cao. Về điểm khác của bạn, nếu bạn có kẻ tấn công có thể liên tục tắt phiên bản redis của bạn, giải pháp cho điều đó có thể không cần sử dụng JWT.
yên tĩnh Kiểm tra

@quietContest nhất quán hoặc sự kiện một lần trong đời đều giống với tôi ở khía cạnh này. tức là một cuộc tấn công DDoS được đặt tốt có thể khiến máy chủ "đăng xuất người dùng". Điều này không tốt cho danh tiếng độ tin cậy của phần mềm. Tôi nghĩ redis dù sao cũng là quá mức cần thiết cho việc quản lý phiên. Nó tốn kém và cần được mở rộng, trong khi (một cách an toàn) lưu trữ JWT trong cookie thì không.
Eyal Perry

1
@quietContest cảm ơn bạn đã đóng góp ý kiến, rất thích cuộc thảo luận!
Eyal Perry

0

Tôi đã có một câu hỏi tương tự khi chọn giữa JWT và mã thông báo + bộ nhớ cache để xác thực người dùng.

Sau khi đọc những bài báo này, tôi thấy rõ ràng những lợi ích mà JWT hứa hẹn không vượt quá những vấn đề mà nó mang lại. Vì vậy, mã thông báo + bộ nhớ cache (Redis / Memcached) là cách tốt nhất cho tôi.

Tiêu đề xác thực so với JWT và phiên - Cách chọn kỹ thuật xác thực phù hợp cho API

Kỹ thuật xác thực cho API

Ngừng sử dụng jwt cho các phiên

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.