Mẫu đăng nhập API REST


181

Tôi đang tạo một api REST, theo sát các đề xuất apigee, sử dụng các danh từ không phải động từ, phiên bản api được nướng vào url, hai đường dẫn api trên mỗi bộ sưu tập, sử dụng BẮT ĐẦU BẮT ĐẦU XÓA, v.v.

Tôi đang làm việc trên hệ thống đăng nhập, nhưng không chắc chắn về cách REST thích hợp để đăng nhập người dùng. Tôi không làm việc về bảo mật tại thời điểm này, chỉ là mô hình đăng nhập hoặc luồng. (Sau này chúng tôi sẽ thêm 2 bước oAuth, với một HMAC, v.v.)

Tùy chọn có thể

  • BÀI ĐĂNG cho một cái gì đó như https://api...com/v1/login.json
  • PUT cho một cái gì đó như https://api...com/v1/users.json
  • Một cái gì đó tôi không có mặc dù ...

Phong cách REST thích hợp để đăng nhập người dùng là gì?


9
Đó là định dạng đáp ứng. .json bảo máy chủ trả lời bằng json, .xml bảo máy chủ trả lời với định dạng xml. Thay vào đó làm cho nó một tham số tùy chọn đằng sau? blog.apigee.com/detail/ từ
Scott Roepnack

28
Không bao giờ thấy đàm phán nội dung được thực hiện trên URL, chỉ trong các tiêu đề. Trên URL, điều đó có nghĩa là bạn mất lợi ích của bộ nhớ đệm và hơn thế nữa.
Oded

10
@ScottRoepnack thì bạn nên xem xét Accepttiêu đề HTTP.
Alessandro Vendruscolo

2
@Oded Nếu bạn đã sử dụng một Accepttiêu đề, bạn cũng sẽ có một Vary: Accept, vì vậy bộ nhớ đệm sẽ không bị ảnh hưởng. Conneg trong phần mở rộng đã được thảo luận trước đó ; Tôi đồng ý với câu trả lời của Shonzilla ở đó.
cmbuckley

2
@Oded - tôi không hiểu. tại sao bạn sẽ mất lợi ích của bộ nhớ đệm nếu bạn chỉ định loại nội dung trong URL (dưới dạng hậu tố .json cho đường dẫn truy vấn hoặc dưới dạng param = json query param)? Và "bạn" là ai trong trường hợp này? Ai là người mất lợi ích bộ nhớ đệm? đối với tôi, dường như các kết quả của bất kỳ truy vấn nào đều có thể được lưu trong bộ nhớ cache bất kể những gì trong đường dẫn truy vấn hoặc tham số.
Cheeso

Câu trả lời:


138

Thiết kế nguyên tắc của kiến ​​trúc web hiện đại của Roy T. Fielding và Richard N. Taylor , tức là chuỗi các công việc từ tất cả các thuật ngữ REST đến từ, chứa định nghĩa về tương tác giữa máy khách và máy chủ:

Tất cả các tương tác REST là không trạng thái . Nghĩa là, mỗi yêu cầu chứa tất cả thông tin cần thiết để trình kết nối hiểu được yêu cầu, không phụ thuộc vào bất kỳ yêu cầu nào có thể xảy ra trước nó .

Hạn chế này thực hiện bốn chức năng, thứ 1 và thứ 3 rất quan trọng trong trường hợp cụ thể này:

  • Thứ nhất : nó loại bỏ bất kỳ nhu cầu nào đối với các trình kết nối để duy trì trạng thái ứng dụng giữa các yêu cầu , do đó giảm tiêu thụ tài nguyên vật lý và cải thiện khả năng mở rộng;
  • Thứ 3 : nó cho phép một bên trung gian xem và hiểu một yêu cầu riêng rẽ , điều này có thể cần thiết khi các dịch vụ được sắp xếp lại một cách linh hoạt;

Và bây giờ hãy quay trở lại trường hợp bảo mật của bạn. Mỗi yêu cầu phải chứa tất cả thông tin bắt buộc và ủy quyền / xác thực không phải là ngoại lệ. Làm thế nào để đạt được điều này? Nghĩa đen gửi tất cả các thông tin cần thiết qua dây với mỗi yêu cầu.

Một trong những ví dụ làm thế nào để lưu trữ điều này là mã xác thực tin nhắn dựa trên hàm băm hoặc HMAC . Trong thực tế điều này có nghĩa là thêm một mã băm của thông điệp hiện tại vào mỗi yêu cầu. Mã băm được tính bằng hàm băm mật mã kết hợp với khóa mật mã bí mật . Hàm băm mật mã được xác định trước hoặc là một phần của khái niệm REST theo yêu cầu mã (ví dụ JavaScript). Khóa mật mã bí mật nên được máy chủ cung cấp cho khách hàng dưới dạng tài nguyên và khách hàng sử dụng nó để tính mã băm cho mọi yêu cầu.

Có rất nhiều ví dụ về việc triển khai HMAC , nhưng tôi muốn bạn chú ý đến ba điều sau đây:

Làm thế nào nó hoạt động trong thực tế

Nếu khách hàng biết khóa bí mật, thì nó đã sẵn sàng để hoạt động với tài nguyên. Nếu không, anh ta sẽ được chuyển hướng tạm thời (mã trạng thái 307 Chuyển hướng tạm thời) để ủy quyền và lấy khóa bí mật, sau đó chuyển hướng trở lại tài nguyên ban đầu. Trong trường hợp này, không cần biết trước (tức là mã cứng ở đâu đó) URL để ủy quyền cho máy khách là gì và có thể điều chỉnh lược đồ này theo thời gian.

Hy vọng điều này sẽ giúp bạn tìm ra giải pháp thích hợp!


23
MAC có nghĩa là để chứng minh quyền tự động của tin nhắn và bảo vệ chống giả mạo - nó không liên quan gì đến xác thực người dùng
yrk

1
Đã thêm một trong các ví dụ, cách xử lý xác thực người dùng / khách hàng mà không cần biết trước " URL đăng nhập "
Akim

Dưới đây là một hai bài báo tốt đẹp với ví dụ stateless auth cho các dịch vụ REST: blog.jdriven.com/2014/10/... technicalrex.com/2015/02/20/...
Vladimir Rozhkov

41

TL; DR Đăng nhập cho mỗi yêu cầu không phải là thành phần bắt buộc để thực hiện bảo mật API, xác thực là.

Thật khó để trả lời câu hỏi của bạn về đăng nhập mà không nói về bảo mật nói chung. Với một số chương trình xác thực, không có thông tin đăng nhập truyền thống.

REST không đưa ra bất kỳ quy tắc bảo mật nào, nhưng cách triển khai phổ biến nhất trong thực tế là OAuth với xác thực 3 chiều (như bạn đã đề cập trong câu hỏi của mình). Không có đăng nhập mỗi lần, ít nhất là không phải với mỗi yêu cầu API. Với auth 3 chiều, bạn chỉ cần sử dụng mã thông báo.

  1. Người dùng phê duyệt ứng dụng khách API và cấp quyền để thực hiện các yêu cầu dưới dạng mã thông báo tồn tại lâu dài
  2. Api client có được mã thông báo tồn tại ngắn bằng cách sử dụng mã thông báo tồn tại lâu.
  3. Api client gửi mã thông báo ngắn hạn với mỗi yêu cầu.

Lược đồ này cung cấp cho người dùng tùy chọn thu hồi quyền truy cập bất cứ lúc nào. Thực tế tất cả các API RESTful có sẵn công khai mà tôi đã thấy sử dụng OAuth để thực hiện điều này.

Tôi chỉ không nghĩ rằng bạn nên đóng khung vấn đề của mình (và câu hỏi) về mặt đăng nhập, mà là nghĩ về việc bảo mật API nói chung.

Để biết thêm thông tin về xác thực API REST nói chung, bạn có thể xem các tài nguyên sau:


Vâng, OAuth! Câu trả lời rất đơn giản, nên là câu trả lời được chấp nhận, imho.
Levite

26

Một phần lớn trong triết lý REST là khai thác càng nhiều tính năng tiêu chuẩn của giao thức HTTP càng tốt khi thiết kế API của bạn. Áp dụng triết lý đó vào xác thực, máy khách và máy chủ sẽ sử dụng các tính năng xác thực HTTP tiêu chuẩn trong API.

Màn hình đăng nhập rất phù hợp cho các trường hợp sử dụng của con người: truy cập màn hình đăng nhập, cung cấp người dùng / mật khẩu, đặt cookie, khách hàng cung cấp cookie đó trong tất cả các yêu cầu trong tương lai. Con người sử dụng trình duyệt web không thể mong đợi cung cấp id người dùng và mật khẩu cho mỗi yêu cầu HTTP riêng lẻ.

Nhưng đối với API REST, màn hình đăng nhập và cookie phiên không thực sự cần thiết, vì mỗi yêu cầu có thể bao gồm thông tin đăng nhập mà không ảnh hưởng đến người dùng; và nếu khách hàng không hợp tác bất cứ lúc nào, một 401phản hồi "trái phép" có thể được đưa ra. RFC 2617 mô tả hỗ trợ xác thực trong HTTP.

TLS (HTTPS) cũng sẽ là một tùy chọn và sẽ cho phép xác thực ứng dụng khách với máy chủ (và ngược lại) trong mọi yêu cầu bằng cách xác minh khóa chung của bên kia. Ngoài ra, điều này đảm bảo kênh cho một phần thưởng. Tất nhiên, một trao đổi khóa trước khi giao tiếp là cần thiết để làm điều này. (Lưu ý, đây là cách đặc biệt để xác định / xác thực người dùng bằng TLS. Bảo mật kênh bằng cách sử dụng TLS / Diffie-Hellman luôn là một ý tưởng hay, ngay cả khi bạn không xác định người dùng bằng khóa chung của nó.)

Một ví dụ: giả sử rằng mã thông báo OAuth là thông tin đăng nhập đầy đủ của bạn. Khi ứng dụng khách có mã thông báo OAuth, nó có thể được cung cấp dưới dạng id người dùng trong xác thực HTTP tiêu chuẩn với mỗi yêu cầu. Máy chủ có thể xác minh mã thông báo trong lần sử dụng đầu tiên và lưu trữ kết quả kiểm tra với thời gian tồn tại được gia hạn với mỗi yêu cầu. Bất kỳ yêu cầu yêu cầu trả lại xác thực 401nếu không được cung cấp.


1
"vì mỗi yêu cầu có thể bao gồm thông tin đăng nhập mà không ảnh hưởng đến người dùng" Xác thực 3 chiều và OAuth được phát minh vì điều trong trích dẫn là không tốt. Nếu bạn cung cấp thông tin đăng nhập với mỗi yêu cầu mà không có cơ chế trên máy chủ để thu hồi chúng, điều đó sẽ không an toàn nếu được sử dụng với SSL.
Slavo

1
Bất cứ khi nào có một khái niệm về người dùng, một cái gì đó phải được truyền từ máy khách đến máy chủ để xác định người dùng nào. Mã thông báo OAuth chắc chắn có thể đóng vai trò là "thông tin đăng nhập" ở đây, thay vì kết hợp mật khẩu / người dùng thực tế. Bảo mật kênh bằng TLS chắc chắn luôn là một điều tốt, nhưng điều đó gần như bên cạnh vấn đề. Ngay cả khi bạn sử dụng cookie, một số loại mã thông báo vẫn được gửi đến máy chủ với mọi yêu cầu, chỉ với một tiêu đề cookie thay vì tiêu đề xác thực.
dâu

Và nếu bạn không sử dụng TLS hoặc OAuth vì bất kỳ lý do gì, việc gửi người dùng / mật khẩu mỗi lần thực sự tồi tệ hơn là chỉ gửi một lần? Nếu kẻ tấn công có thể có được người dùng / mật khẩu, kẻ tấn công có thể cũng có được cookie phiên.
dâu

Sự khác biệt giữa cookie và tiêu đề xác thực là thông tin đăng nhập là cookie luôn được liên kết với một tên miền cụ thể. Điều này có nghĩa là khi API nhận được cookie, nó biết nó đến từ đâu (được viết bởi cùng một tên miền trước đó). Với một tiêu đề, bạn không bao giờ biết và bạn phải thực hiện kiểm tra cụ thể cho việc này. Nói chung, tôi đồng ý, cả hai đều là thông tin đăng nhập, nhưng tôi nghĩ rằng việc thông tin đăng nhập không phải là thông tin đăng nhập. Đăng nhập là hành động tích cực của việc mở cửa. Trong trường hợp xác thực 3 chiều, chỉ có sự chấp thuận đầu tiên của khách hàng sẽ được đăng nhập.
Slavo
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.