2011-08-30 26 views
72

Khi thiết kế REST API, việc xác thực người dùng trước có phổ biến không?Bảo mật REST API mà không cần phát minh lại bánh xe

Các trường hợp sử dụng điển hình tôi đang tìm kiếm là:

  • Người dùng muốn có được dữ liệu. Chắc chắn chúng tôi muốn chia sẻ! Nhận khóa API công khai và đọc đi!
  • Người dùng muốn lưu trữ/cập nhật dữ liệu ... woah chờ đã! bạn là ai, bạn có thể làm điều này?

Tôi muốn xây dựng ứng dụng này một lần và cho phép nói ứng dụng web, ứng dụng Android hoặc ứng dụng iPhone để sử dụng ứng dụng đó.

API REST dường như là lựa chọn hợp lý với các yêu cầu như thế này

Để minh họa câu hỏi của tôi, tôi sẽ sử dụng một ví dụ đơn giản.

Tôi có một mục trong cơ sở dữ liệu, có một thuộc tính xếp hạng (số nguyên từ 1 đến 5).

Nếu tôi hiểu REST của một cách chính xác tôi sẽ thực hiện một yêu cầu GET bằng cách sử dụng ngôn ngữ của sự lựa chọn của tôi mà trả csv, xml hoặc json như thế này:

http://example.com/product/getrating/{id}/ 

Giả sử chúng ta chọn JSON chúng tôi quay trở lại:

{ 
    "id": "1", 
    "name": "widget1", 
    "attributes": { "rating": {"type":"int", "value":4} } 
} 

Điều này phù hợp với API công khai. Tôi nhận được phần đó.

Trường hợp tôi có tấn câu hỏi là làm cách nào để kết hợp điều này với mô hình bảo mật? Tôi quen với bảo mật ứng dụng web nơi tôi có trạng thái phiên xác định người dùng của mình mọi lúc để tôi có thể kiểm soát những gì họ có thể làm bất kể họ quyết định gửi gì cho tôi. Vì tôi hiểu nó không phải là RESTful nên sẽ là một giải pháp tồi trong trường hợp này.

Tôi sẽ cố sử dụng một ví dụ khác sử dụng cùng một mục/xếp hạng.

Nếu người sử dụng "JOE" muốn thêm một giá đến một mục

Điều này có thể được thực hiện bằng:

http://example.com/product/addrating/{id}/{givenRating}/ 

Tại thời điểm này, tôi muốn để lưu trữ các dữ liệu nói rằng " JOE "đã đưa ra sản phẩm {id} xếp hạng {givenRating}.

Câu hỏi: Làm cách nào để biết yêu cầu đến từ "JOE" chứ không phải "BOB".

Hơn nữa, điều gì sẽ xảy ra nếu dữ liệu hợp lý hơn giống như số điện thoại của người dùng?

Những gì tôi đã có cho đến nay là:

1) Sử dụng được xây dựng trong tính năng của HTTP để xác thực ở mọi yêu cầu, hoặc là đồng bằng HTTP hoặc HTTPS.

Điều này có nghĩa rằng tất cả các yêu cầu hiện nay mang hình thức của:

https://joe:[email protected]/product/addrating/{id}/{givenRating}/ 

2) Sử dụng một cách tiếp cận như S3 của Amazon với tư nhân và công cộng quan trọng: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3) Sử dụng một cookie anyway và phá vỡ phần không trạng thái của REST.

Cách tiếp cận thứ hai có vẻ tốt hơn với tôi, nhưng tôi tự hỏi liệu tôi có thực sự phải phát minh lại toàn bộ điều này không? Hashing, lưu trữ, tạo ra các phím, vv tất cả bởi bản thân mình?

Điều này nghe rất giống với việc sử dụng phiên trong ứng dụng web điển hình và tự viết lại toàn bộ ngăn xếp, thường với tôi có nghĩa là "Bạn đang làm sai" đặc biệt là khi xử lý bảo mật.

EDIT: Tôi đoán tôi cũng nên đề cập đến OAuth.

+4

Nếu bạn đang gửi tên người dùng và mật khẩu theo mọi yêu cầu, ** sử dụng HTTPS **. –

+51

Không có gì để làm với bảo mật, nhưng một RESTful API sẽ không sử dụng 'getrating' và' andrating'; nó sẽ chỉ là 'xếp hạng' và bạn sẽ GET, POST, PUT hoặc DELETE với tài nguyên đó. – Duncan

Trả lời

20

Sửa 5 năm sau

Sử dụng OAuth2!

phiên bản trước

Không, hoàn toàn không có nhu cầu sử dụng cookie. Nó không an toàn một nửa như HTTP Digest, OAuth hoặc AWS của Amazon (không khó sao chép).

Cách bạn nên xem xét cookie là mã thông báo xác thực nhiều như Basic/Digest/OAuth/tùy theo điều kiện nào, nhưng ít phù hợp hơn.

Tuy nhiên, tôi không cảm thấy việc sử dụng cookie đi ngược lại các nguyên tắc RESTful mỗi se, miễn là nội dung của cookie phiên không ảnh hưởng đến nội dung của tài nguyên bạn quay trở lại từ máy chủ.

Cookie ác, ngừng sử dụng chúng.

+2

Tôi không tìm thấy cách của Amazon khó sao chép cho mỗi câu nói ... như tôi không tìm thấy viết JavaScript từ đầu "cứng", nhưng jQuery chắc chắn giúp viết nó tốt. Đọc về nó để lại cho tôi tự hỏi không có một khuôn khổ để trừu tượng điều này? – jfrobishow

+1

Google. Tôi đã viết một triển khai cho AWS, nhưng nó không hoàn chỉnh Tôi tin rằng: http://code.google.com/p/sabredav/source/browse/lib/Sabre/HTTP/AWSAuth.php – Evert

+2

Xin lỗi nhưng câu trả lời là không chính xác. Cookie và HTTP Digest là bổ sung nhưng trực giao - bạn có thể sử dụng thứ hai để xác thực người dùng và phát hành cookie. So sánh với OAuth, bảo mật dựa trên cookie sẽ không hoạt động khi bạn có dịch vụ tên miền chéo hoặc bạn đang cho phép những người không đáng tin cậy khác viết khách hàng vào dịch vụ của bạn (các bên thứ 3 liên quan) và muốn cho phép người dùng của bạn thu hồi quyền truy cập ứng dụng. Nhưng trong các trường hợp khác, nó hoạt động chính xác như OAuth, bạn có thể nghĩ về cookie như một mã thông báo truy cập OAuth, theo cách bạn cần lưu trữ ở đâu đó. – zihotki

21

Đừng lo lắng về việc "Nghỉ ngơi", lo lắng về bảo mật. Đây là cách tôi thực hiện:

Bước 1: Người dùng truy cập dịch vụ xác thực bằng thông tin đăng nhập.

Bước 2: Nếu thông tin đăng nhập kiểm tra, hãy quay lại dấu vân tay, id phiên, v.v ... và đưa chúng vào bộ nhớ dùng chung để truy xuất nhanh sau hoặc sử dụng cơ sở dữ liệu nếu bạn không bận tâm thêm vài mili giây thời gian quay vòng dịch vụ web.

Bước 3: Thêm lệnh gọi điểm vào đầu mỗi tập lệnh dịch vụ web xác thực mã nhận dạng và id phiên cho mọi yêu cầu dịch vụ web.

Bước 4: Nếu vân tay và id phiên không hợp lệ hoặc đã chuyển hướng hết thời gian sang xác thực.

đọc:

RESTful Authentication

+3

Nhưng sau đó bạn không bắt buộc người dùng phải đăng nhập trước khi truy cập vào API mỗi lần "phiên" hết hạn? Trong trường hợp thiết bị di động bạn làm gì? Cung cấp cho họ "khóa" vĩnh viễn để họ không phải đăng nhập mỗi khi họ sử dụng ứng dụng sử dụng API? – jfrobishow

+1

Tôi buộc họ phải đăng nhập. Đó là hoặc là sử dụng cookie hoặc ánh xạ vân tay cho UDID của họ, nhưng điều UDID có nghĩa là người dùng phải truy cập dịch vụ từ cùng một thiết bị. –

+0

Về bước 3: điều này có nghĩa là nếu tôi đang sử dụng một khung MVC sử dụng "Hành động" bên trong "Bộ điều khiển", tôi nên đặt vào mỗi Hành động hai tham số bổ sung (vân tay và sessionid)? – sports

7

Sửa 3 năm sau

Tôi hoàn toàn đồng ý với Evert, sử dụng OAuth2 với HTTPS, và không phát minh lại bánh xe! :-)

Bằng các API REST đơn giản hơn - không dành cho khách hàng của bên thứ ba - JSON Web Tokens cũng có thể tốt.

phiên bản trước

Sử dụng một cookie anyway và phá vỡ một phần không quốc tịch của REST.

Không sử dụng phiên, với các phiên dịch vụ REST của bạn sẽ không thể mở rộng tốt ... Có 2 trạng thái ở đây: trạng thái ứng dụng (hoặc trạng thái khách hàng hoặc phiên) và trạng thái tài nguyên. Trạng thái ứng dụng chứa dữ liệu phiên và nó được duy trì bởi máy khách REST. Trạng thái tài nguyên chứa các thuộc tính tài nguyên và các mối quan hệ và được duy trì bởi dịch vụ REST. Bạn có thể quyết định rất dễ dàng cho dù một biến cụ thể là một phần của trạng thái ứng dụng hay trạng thái tài nguyên. Nếu số lượng dữ liệu tăng cùng với số phiên hoạt động, thì dữ liệu đó sẽ thuộc về trạng thái ứng dụng. Vì vậy, ví dụ nhận dạng người dùng của phiên hiện tại thuộc về trạng thái ứng dụng, nhưng danh sách người dùng hoặc quyền người dùng thuộc về trạng thái tài nguyên.

Vì vậy, máy khách REST nên lưu trữ các yếu tố nhận dạng và gửi chúng với mọi yêu cầu. Đừng nhầm lẫn giữa máy khách REST với máy khách HTTP. Chúng không giống nhau. REST client cũng có thể ở phía máy chủ nếu nó sử dụng curl, hoặc nó có thể tạo ra ví dụ một cookie chỉ phía máy chủ http mà nó có thể chia sẻ với dịch vụ REST thông qua CORS. Điều duy nhất quan trọng là dịch vụ REST phải xác thực bằng mọi yêu cầu, vì vậy bạn phải gửi thông tin đăng nhập (tên người dùng, mật khẩu) với mọi yêu cầu.

  • Nếu bạn viết máy khách REST phía máy khách, thì điều này có thể được thực hiện với SSL + HTTP auth. Trong trường hợp đó, bạn có thể tạo bộ nhớ cache credentials -> (identity, permissions) trên máy chủ để xác thực nhanh hơn. Hãy lưu ý rằng nếu bạn xóa bộ nhớ cache đó và người dùng gửi cùng một yêu cầu, họ sẽ nhận được phản hồi tương tự, chỉ cần lâu hơn một chút. Bạn có thể so sánh điều này với phiên: nếu bạn xóa cửa hàng phiên, thì người dùng sẽ nhận được phản hồi status: 401 unauthorized ...
  • Nếu bạn viết máy khách REST phía máy chủ và gửi yếu tố nhận dạng tới dịch vụ REST qua curl, thì bạn có 2 lựa chọn. Bạn cũng có thể sử dụng http auth hoặc bạn có thể sử dụng trình quản lý phiên trong trình khách REST của bạn nhưng không thể sử dụng trong dịch vụ REST.
  • Nếu ai đó không tin tưởng vào máy khách REST của bạn, thì bạn phải viết một ứng dụng để xác thực người dùng và cung cấp cho họ tính khả dụng để quyết định xem họ có muốn cấp quyền cho các máy khách khác nhau hay không. Oauth là một giải pháp đã tồn tại cho điều đó. Oauth1 an toàn hơn, oauth2 kém an toàn hơn nhưng đơn giản hơn, và tôi đoán có một số giải pháp khác cho vấn đề này ... Bạn không cần phải tái tạo lại điều này. Có các giải pháp xác thực và ủy quyền hoàn chỉnh bằng oauth, ví dụ: wso identity server.

Cookie không nhất thiết phải là xấu. Bạn có thể sử dụng chúng theo cách RESTful cho đến khi chúng giữ trạng thái máy khách và dịch vụ chỉ giữ trạng thái tài nguyên. Ví dụ: bạn có thể lưu trữ giỏ hàng hoặc cài đặt phân trang ưa thích trong cookie ...

+1

Làm thế nào mà không phải trên đầu trang của 'Đừng lo lắng về việc được" RESTful ", lo lắng về bảo mật.' câu trả lời? –

+0

Đã quá muộn và tôi không biết bạn đang nói về điều gì, xin lỗi. : D Tôi sẽ đọc bài đăng này vào ngày mai, tôi không nhớ về nó ... – inf3rno

+2

Tôi đã đọc được bài đăng một lần nữa. Yepp, tôi nghĩ đó là vì bài đăng của tôi có độ trễ 2 năm so với bài đăng bạn đã đề cập. Đó là tất cả, có một buổi tối tốt đẹp! :-) – inf3rno

Các vấn đề liên quan