如何设计一个允许安全地跨域脚本编写的 javascript API?
我喜欢使用 Google 地图 api 的方式,使用脚本包含,但我担心:
我的 api 是“半私有”的,也就是说,可以通过互联网访问,但应该允许安全传输数据和某种类型的数据。验证。数据应通过网络保持私密性,并且一个消费者不应该能够获取另一个消费者的数据。
如何使用 SSL 和某种身份验证来保证数据安全,同时仍然可以从纯 HTML 页面“水平”访问,而不需要服务器端代理?我需要管理密钥吗?如何将密钥发布到服务器而不被拦截?我可以使用 OpenId(或其他第三方身份验证)来对 api 用户进行身份验证,还是必须创建自己的身份验证机制?我查遍了 Google,但找不到安全设计和部署 API 的良好指南。
现在我使用 REST 和 AJAX 来使用它们,但跨域调用是不可能的。任何帮助或正确方向的指示将不胜感激。
I like the way Google Maps' api is consumed, using a script include, but I'm worried:
My api is "semi-private", that is, accessible over the internet but should allow for secure transmission of data and some kind of authentication. The data should remain private over the wire, and one consumer shouldn't be able to get at another's data.
How can I use SSL and some kind of authentication to keep the data secure, but still accessible "horizontally" from a plain HTML page with no server-side proxy required? Do I need to manage keys? How will the keys be posted to the server without being intercepted? Can I use OpenId (or some other 3rd-party authentication) to authenticate api users, or do I have to create my own authentication mechanism? I've been all over Google and can't find a good guide to designing and deploying my API securely.
Right now I'm using REST and AJAX to consume them, but cross-domain calls are impossible. Any help or a pointer in the right direction would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我可能会使用动态生成的脚本标记和 SSL URL,其中在查询字符串中包含经过公钥加密的密钥。服务器将使用私钥解密查询字符串参数并返回包含相关信息的脚本(如果密钥无效,则不包含相关信息)。或者类似的东西。但我承认我实际上并没有必要在实践中这样做。
我还会寻找现有技术,例如 Amazon 的 S3 服务。
所以:
script
标签,其中包含 URL您很可能需要两个周期,因为否则对服务器的请求可能会通过中间人攻击而被重复使用。这将是:
script
标签,该标签请求唯一密钥(可能带有一些令人困惑的信息,例如源 IP 和一些随机的进一步密钥)script
标签,其中包括 URL但我实际上没有这样做过。 (或者我有吗?BWAa-ha-ha-ha...) FWIW。
I'd probably use a dynamically-generated script tag with an SSL URL that included a key in the query string that was public-key encrypted. The server would use the private key to decrypt the query string parameter and return script that included the relevant information (or didn't, if the key was invalid). Or something along those lines. But I'll admit that I haven't actually had to do it in practice.
I'd also look for prior art, like Amazon's S3 service.
So:
script
tag that includes the URLYou may well need two cycles, because otherwise the request to the server could be re-used via a man-in-the-middle attack. That would be:
script
tag that requests a unique key (probably with some confounding information, like the source IP and some random further key)script
tag that includes the URLNone of which I've actually done. (Or have I? BWAa-ha-ha-ha...) FWIW.
OAuth 可能会帮助解决这种情况,方法是让用户登录到第 3 方应用程序,并允许您的应用程序在您发出 xhr 请求时使用请求令牌代表他们访问第 3 方。 http://oauth.net/documentation/getting-started/
====== ==
使用服务器端代理的原因归结为网络浏览器内置的同源策略: http ://en.wikipedia.org/wiki/Same_origin_policy
本质上,浏览器只允许向页面来源的地址发出请求(例如,facebook.com 只能向 facebook.com URI 发出请求)。服务器端代理通过向当前源之外的服务器发出请求来解决此问题。服务器端代理也是发出此类请求的最佳实践。
OAuth might help with this situation by having the user login to the 3rd-party application and allowing your application to access the 3rd-party on their behalf by using a request token when you make xhr requests. http://oauth.net/documentation/getting-started/
========
The reason for using a server-side proxy boils down to the Same-origin policy built into web browsers: http://en.wikipedia.org/wiki/Same_origin_policy
Essentially the browser only allows requests to be made to the address in which the page comes from (e.g. facebook.com can only make requests to facebook.com URIs). A server-side proxy solves this issue by making requests to servers outside the current origin. Server-side proxies are also the best practice for making requests like this.
查看开源 javascript Forge 项目。它提供了 javascript TLS 实现,允许安全的跨域 xhr 请求。它可能对您有用:
http://digitalbazaar.com/2010/ 07/20/javascript-tls-1/
http:// digitalbazaar.com/2010/07/20/javascript-tls-2/
https://github.com /digitalbazaar/forge
一种可能的解决方案:
Check out the opensource javascript Forge project. It provides a javascript TLS implementation that allows secure cross-domain xhr requests. It might be of use to you:
http://digitalbazaar.com/2010/07/20/javascript-tls-1/
http://digitalbazaar.com/2010/07/20/javascript-tls-2/
https://github.com/digitalbazaar/forge
One potential solution:
或者,如果您确实不信任第三方 - 在 iframe 内进行身份验证(那么不需要 oauth,只需使用纯 html 表单)并使用 easyXDM 传达外部页面需要了解的有关用户的任何信息。
Or if you really don't trust the third party - do your authentication inside the iframe (no need for oauth then, just use a plain html form) and communicate anything the outer page needs to know about the user using easyXDM.
不太确定问题到底是什么,我认为您正在尝试对 [https://secure.com] 进行类似 jsonp 的调用,以便处理/显示 [http://regular.com] 上的数据]?
两台服务器可以互相通信吗?怎么样:
用户登录 [https://secure.com]
身份验证后,secure.com 生成一个令牌(让我们称之为 syntoken)并将其直接传递到regular.com(服务器到服务器),可能就像一个 session_id、一些任意消息和一个 otp 密码(让我们称之为syncipher)。
Broswer 接收 session_id cookie,然后 Secure.com 将浏览器重定向到 http:// /regular.com/setcookieandredirect?session_id=blabla&otpencryptedsynmessage=blabla
Regular.com 使用 session_id 查找 otp 密码:密钥,并解密 otp 加密消息“blabla”。
如果解密的消息与合成令牌中的原始消息匹配,我们可以验证用户是否已登录[regular.com],并且regular.com生成另一个令牌(我们称之为acktoken,lolz)并将其直接传递到[secure.com] ],由 session_id、一些任意 ack 消息和不同的 otp 密码(我们称之为 ackcipher)组成。
Regular.com 然后向浏览器发送一个由 otpencryptedackmessage 组成的 cookie(让我们将此 cookie 命名为“verified_session”)。
完成页面加载。
从那里,您可以对
https://secure.com 进行类似 jsonp 的调用/getscript.js?query=dataname&verifiedtoken=(verified_sessions_cookie_value)
其中 secure.com/getscript.js 将获取 verifytoken,根据 [secure.com] 发送的原始 cookie session_id 作为密钥查找 ackcipher ,并解密 otpencrypedack 消息,如果解密的消息与 ack 消息匹配,则呈现脚本文件。
这有点像三向握手,秘密在于服务器必须能够直接相互通信以传递密钥。您不必为两台服务器使用相同的 session_id,我只是将其用作寻找访问 syn/ack otp 密码的方法的简单参考点。密码必须对公众完全隐藏。
Not too sure of what the question is exactly, I take it you're attempting to do a jsonp-like call to [https://secure.com] in order to process/display data on [http://regular.com]?
Can the two servers talk to each other? How about something like this:
User logs in on [https://secure.com]
Upon authentication, secure.com generates an token (lets call it syntoken) and passes it directly to regular.com (server-to-server), maybe like a session_id, some arbitrary message, and an otp cipher (lets call it syncipher).
Broswer receives a session_id cookie, and Secure.com then redirects the browser to http://regular.com/setcookieandredirect?session_id=blabla&otpencryptedsynmessage=blabla
Regular.com looks up otp cipher using session_id as a key, and decrypts otpencryptedmessage "blabla."
If decrypted message matches the original message in the syntoken, we can verify user is logged in [regular.com] and regular.com generates another token (lets call it acktoken, lolz) and passes it directly to [secure.com], consisting of session_id, some arbitrary ack message, and a different otp cipher (lets call it ackcipher).
Regular.com then sends the browser a cookie consisting of otpencryptedackmessage (let's name this cookie "verified_session").
Finish loading the page.
From there, you can do jsonp-like calls to
https://secure.com/getscript.js?query=dataname&verifiedtoken=(verified_sessions_cookie_value)
where secure.com/getscript.js will take the verifiedtoken, lookup the ackcipher based on the original cookie session_id sent by [secure.com] as the key, and decrypt the otpencrypedackmessage. If the decrypted message matches the ack message, render the script file.
It's kinda like a 3-way handshake. The secret sauce is that the servers have to be able to talk to each other directly to pass secret keys discretely. You don't have to use the same session_id for both servers, I was just using that as an easy point of reference to find a way to access the syn/ack otp ciphers. The ciphers must be completely hidden from public.