2010-10-30 5 views
16

Tôi thích cách api của Google Maps được sử dụng, sử dụng tập lệnh bao gồm, nhưng tôi lo lắng:Tôi làm cách nào để thiết kế một API javascript cho phép viết kịch bản lệnh giữa nhiều miền một cách an toàn?

Api của tôi là "nửa riêng tư", có thể truy cập qua internet nhưng phải cho phép truyền an toàn dữ liệu và một số loại xác thực. Dữ liệu phải được giữ riêng tư trên dây và một người tiêu dùng không thể nhận dữ liệu của người khác.

Làm cách nào để sử dụng SSL và một số loại xác thực để giữ an toàn cho dữ liệu, nhưng vẫn có thể truy cập "theo chiều ngang" từ trang HTML thuần túy không yêu cầu proxy phía máy chủ? Tôi có cần quản lý khóa không? Các khóa sẽ được đăng lên máy chủ mà không bị chặn như thế nào? Tôi có thể sử dụng OpenId (hoặc một số xác thực của bên thứ ba khác) để xác thực người dùng api hay tôi phải tạo cơ chế xác thực của riêng mình? Tôi đã ở trên Google và không thể tìm thấy hướng dẫn tốt để thiết kế và triển khai API của tôi một cách an toàn.

Hiện tại tôi đang sử dụng REST và AJAX để tiêu thụ chúng, nhưng các cuộc gọi tên miền chéo là không thể. Bất kỳ trợ giúp hoặc một con trỏ trong đúng hướng sẽ được nhiều đánh giá cao.

+1

Một vấn đề nhỏ - làm cách nào Bạn mong đợi các khóa hoặc mật khẩu được bảo mật khi máy khách đang ở dạng javascript? tất cả "bán riêng tư" là minh bạch cho bất kỳ ai nhìn trộm mã. – naugtur

+0

Ông có thể tạo chứng chỉ phía máy khách và lưu trữ chúng bằng cách sử dụng flash/HTML5 lưu trữ cục bộ ... và sau đó có các trang web chuyển thông số qua URL hoặc window.name tới iframe sẽ sử dụng chứng chỉ trong cuộc gọi an toàn để tìm nạp dữ liệu được hiển thị trong khung nội tuyến (để tránh phải sử dụng cookie hoặc quá trình đăng nhập). – dlongley

+0

@naugtur: đó là lý do tại sao tôi đăng câu hỏi :) –

Trả lời

10

Tôi có thể sử dụng thẻ tập lệnh được tạo động với URL SSL bao gồm một khóa trong chuỗi truy vấn được mã hóa khóa công khai. Máy chủ sẽ sử dụng khóa riêng để giải mã tham số chuỗi truy vấn và trả về tập lệnh bao gồm thông tin có liên quan (hoặc không, nếu khóa không hợp lệ). Hoặc một cái gì đó dọc theo các đường dây. Nhưng tôi sẽ thừa nhận rằng tôi đã không thực sự phải làm điều đó trong thực tế.

Tôi cũng sẽ tìm kiếm các tác phẩm nghệ thuật trước, như dịch vụ S3 của Amazon.

Vì vậy:

  1. dùng cung cấp bí mật mã
  2. Client-side sử dụng khóa công khai để mã hóa gắn thêm các bí mật
  3. JavaScript thẻ script bao gồm các URL
  4. Server xử lý yêu cầu kịch bản, giải mã bí mật, kiểm tra và gửi trả lời có liên quan.

Bạn cũng có thể cần hai chu kỳ, bởi vì nếu không yêu cầu đến máy chủ có thể được sử dụng lại thông qua một cuộc tấn công trung gian. Đó sẽ là:

  1. JavaScript gắn thẻ script mà yêu cầu một khóa duy nhất (có lẽ với một số thông tin gây nhiễu, giống như IP nguồn và một số chính tiếp tục ngẫu nhiên)
  2. Server đáp ứng với một phím một lần gắn với rằng IP
  3. dùng cung cấp bí mật
  4. client-side code sử dụng khóa công khai để mã hóa bí mật, trong đó có chìa khóa độc đáo từ # 1
  5. JavaScript gắn thẻ script bao gồm các URL
  6. Máy chủ xử lý yêu cầu tập lệnh, giải mã bí mật, kiểm tra và gửi lại phản hồi có liên quan.
  7. Câu trả lời cũng có thể được mã hóa (ở một mức độ) sử dụng phím ngẫu nhiên bao gồm trong # 1

Không ai trong số đó tôi đã thực sự thực hiện. (Hoặc có tôi? BWAa-ha-ha-ha ...) FWIW.

0

OAuth có thể trợ giúp với trường hợp này bằng cách đăng nhập người dùng vào ứng dụng của bên thứ ba và cho phép ứng dụng của bạn truy cập bên thứ ba nhân danh họ bằng cách sử dụng mã thông báo yêu cầu khi bạn thực hiện yêu cầu xhr. http://oauth.net/documentation/getting-started/

========

Lý do cho việc sử dụng một proxy server-side nắm để chủ trương Same-nguồn gốc xây dựng vào trình duyệt web: http://en.wikipedia.org/wiki/Same_origin_policy

Về cơ bản trình duyệt duy nhất cho phép yêu cầu được thực hiện theo địa chỉ mà trang đến từ (ví dụ: facebook.com chỉ có thể gửi yêu cầu tới URI facebook.com). Proxy phía máy chủ giải quyết vấn đề này bằng cách gửi yêu cầu tới máy chủ bên ngoài nguồn gốc hiện tại. Proxy phía máy chủ cũng là phương pháp hay nhất để thực hiện các yêu cầu như thế này.

+0

Tôi sẽ xem xét việc thiết lập proxy phía máy chủ là hơi nặng đối với dữ liệu chỉ đọc. Tôi muốn bật "mash-up" an toàn để thực thi trong trình duyệt. –

0

Kiểm tra dự án javascript Forge mã nguồn mở. Nó cung cấp một triển khai TLS javascript cho phép yêu cầu xhr qua miền an toàn. Nó có thể được sử dụng cho bạn:

http://digitalbazaar.com/2010/07/20/javascript-tls-1/

http://digitalbazaar.com/2010/07/20/javascript-tls-2/

https://github.com/digitalbazaar/forge

Một giải pháp tiềm năng:

  1. Thiết lập một máy chủ Apache để chạy trang web của bạn.
  2. Nhận chứng chỉ SSL cho trang web của bạn.
  3. Cài đặt mod apache đi kèm với Forge để thiết lập chính sách tên miền chéo cho phép các trang web khác truy cập vào trang web của bạn.
  4. Triển khai TLS của Host Forge trên trang web của bạn cùng với chứng chỉ trang web của bạn ở định dạng PEM.
  5. Yêu cầu các trang web khác bao gồm javascript từ trang web của bạn và sử dụng nó để thực hiện cuộc gọi an toàn đến trang web của bạn để làm bất cứ điều gì bạn muốn.
+0

Không chắc chắn trường hợp sử dụng phức tạp của bạn ở đây ... nhưng nếu trang web khác không cần truy cập vào dữ liệu được trả về từ API theo bất kỳ cách nào (hoặc không đáng tin cậy), thì chỉ cần sử dụng iframe có thể hoàn thành công việc . – dlongley

0
  1. (bên thứ ba) Trang sử dụng OAUTH hoặc điều gì đó tương tự để xác thực người dùng và nhận mã thông báo từ máy chủ của bạn.
  2. Trang tải IFRAME từ máy chủ của bạn thông qua SSL truyền mã thông báo để xác thực.
  3. IFRAME có thể liên lạc an toàn với máy chủ của bạn qua SSL
  4. Sử dụng easyXDM hoặc điều gì đó tương tự để giao tiếp giữa IFRAME và trang bên thứ ba, sử dụng một số API giống như socket hoặc RPC hạn chế mà bạn tạo.

Hoặc nếu bạn thực sự không tin tưởng bên thứ ba - thực hiện xác thực của bạn bên trong khung nội tuyến (không cần oauth, chỉ cần sử dụng biểu mẫu html thuần túy) và giao tiếp bất cứ điều gì bên ngoài cần biết về người dùng sử dụng easyXDM.

0

Không quá chắc chắn về câu hỏi là chính xác, tôi lấy nó bạn đang cố gắng thực hiện cuộc gọi giống như jsonp tới [https://secure.com] để xử lý/hiển thị dữ liệu trên [http://regular.com]?

Hai máy chủ có thể nói chuyện với nhau không?Làm thế nào về một cái gì đó như thế này:

  1. tài khoản đăng nhập vào trên [https://secure.com]

  2. Sau khi xác thực, secure.com tạo ra một token (cho phép gọi nó syntoken) và vượt qua nó trực tiếp đến regular.com (máy chủ đến máy chủ), có thể giống như session_id, một số thông báo tùy ý và mật mã otp (cho phép gọi nó là đồng bộ hóa).

  3. broswer nhận một cookie session_id và Secure.com sau đó chuyển hướng trình duyệt để http://regular.com/setcookieandredirect?session_id=blabla&otpencryptedsynmessage=blabla

  4. Regular.com nhìn lên mã otp sử dụng session_id như một chìa khóa, và giải mã otpencryptedmessage "blabla."

  5. Nếu thư được giải mã khớp với thư gốc trong cú pháp, chúng tôi có thể xác minh người dùng được đăng nhập [regular.com] và regular.com tạo mã thông báo khác (cho phép gọi nó là acktoken, lolz) và chuyển trực tiếp đến [secure .com], bao gồm session_id, một số thông điệp ack tùy ý và một mật mã otp khác (cho phép gọi nó là ackcipher).

  6. Regular.com sau đó gửi trình duyệt một cookie chứa otpencryptedackmessage (hãy đặt tên cho cookie này là "verified_session").

  7. Hoàn tất tải trang.

Từ đó, bạn có thể thực hiện cuộc gọi jsonp giống như để

https://secure.com/getscript.js?query=dataname&verifiedtoken=(verified_sessions_cookie_value)

nơi secure.com/getscript.js sẽ lấy verifiedtoken, tra cứu ackcipher dựa trên cookie session_id gốc được gửi bởi [secure.com] làm khóa và giải mã otpencrypedackmessage. Nếu thông báo được giải mã khớp với thông điệp ack, hãy hiển thị tệp tập lệnh.

Nó giống như một cái bắt tay 3 chiều. Nước sốt bí mật là các máy chủ phải có khả năng nói chuyện trực tiếp với nhau để truyền các khóa bí mật một cách kín đáo. Bạn không phải sử dụng cùng session_id cho cả hai máy chủ, tôi chỉ sử dụng nó như là một điểm tham chiếu dễ dàng để tìm cách truy cập mật mã đồng bộ/ack otp. Mật mã phải được ẩn hoàn toàn khỏi công chúng.