2013-01-10 143 views
22

我正在构建一个PHP REST API,该API将从JavaScript客户端使用,并且在解决如何实现身份验证和访问方面存在一些问题。将会有多个应用程序将使用我将开发的JavaScript库来与我的应用程序进行对话和交互。我将为每个人提供API密钥,所以这不是问题。JavaScript客户端对REST API的授权和身份验证

我开始感到困惑的是如何让这些网站上的用户对我的应用程序进行身份验证。这个外部网站存储我的用户的帐户和密码信息似乎是个不错的主意;所以,我想我应该让我的JavaScript库包含一个登录窗口小部件,用于请求我的应用程序的用户帐户信息。

如果身份验证在那里成功,由于我正在使用REST API,因此我需要将检索到的令牌存储在客户端Cookie或其他内容中,以便用户无需再次登录到我的应用程序在外部网站的每个页面上。但是,如果用户从外部站点注销,然后另一个用户从同一浏览器登录,会发生什么情况?就我的JavaScript库而言,旧用户仍然会登录到我的应用程序中,因为Cookie /令牌还没有过期 - 当前一个用户的会话结束时,如何清除cookie?或者,我在这里完全脱离正确的道路吗?

所以,我想过程会是这样的:

埋在这里
var token; // Some hashed string containing an expiration date and user id 
var apiKey = '123abc'; 

// Read the cookie and check if it already contains the token 
token = readCookie('token'); 
if (token == '') { 
    // get username and password from user through some prompt 

    var request_data = {apiKey: apiKey, user: username, pass: password}; 
    $.post('https://service.com/api/user/login', request_data, function(data) { 
     token = data; 
     document.cookie = "token=" + token; 
    }); 
} 

... 

var get_data = {apiKey: apiKey, token: token}; 
$.get('http://service.com/api/<object>', get_data, function(data) { 
    // Do something with data 
}); 

对不起,有几个问题。我猜最主要的是如果我将令牌存储到cookie中,如何确保在用户注销外部应用程序时将其清除?或者,如果我不应该将它存储到cookie中,我如何让客户端知道用户的状态?

+0

我想你应该在你的js API中提供一些'login' /'logout'方法,你的客户端(那些在应用程序中使用你的库的站点)应该根据他们的本地登录/注销顺序调用。如果他们不需要认证,恐怕你无法拦截一个用户在同一个浏览器中(例如,在某个网吧)接替另一个用户的时刻。 – Stan

回答

40

我建议您阅读very good blog post关于保护RESTful API的安全。

(在情况下链接不起作用—它已经死了一次,并且必须从archive.org —检索到的,我发现它似乎是一个PDF渲染这个页面可以访问这里:https://www.ida.liu.se/~TDDD97/labs/hmacarticle.pdf

注意:我的回答是偏离主题,因为上面的博客文章中提供的解决方案不是从Javascript客户端安全的。实际上,它主要解释如何在服务器端保护REST API。

+6

我读过的第一件事并没有以“如此使用OAuth”来结束......并且奖金非常直截了当,特别是如果您已经了解了基本密码学结构的一小部分。很棒的发现。 – Kaganar

+5

如果您从JS客户端使用HMAC,则客户端应该拥有密钥来签署请求,从而将其公开化,这使得它无用。 –

+0

由于该链接现在已经多次下降,因此可能需要重新回顾这个答案,并将链接中的重要信息整合到答案本身中。您可以通过引用重要的位(使用blockquote格式)和/或通过汇总它们(使用您自己的单词)来做到这一点。离开链接以提供上下文。我认为这是值得的,因为这已经被证明是多年来非常受欢迎的答案。 –

1

如果它是一个私有API(你有一个用户表)从另一个主机名跨域到你自己的主机名,我同意上面的建议,并提出一个简单的(SSL)登录/注销,可以给你的用户(或带走)来自你的域名的cookie。

如果是公共API(任何人都可以获得API密钥),我建议使用上面的答案在博客文章中的方法。

对于JavaScript客户端,尝试https://github.com/jpillora/jquery.rest,如有丢失,提交功能请求,或者如果你喜欢:)

8

“我在哪里开始越来越困惑的是如何对这些网站的用户进行身份验证,以我的申请作出贡献。这个外部网站存储我的用户的帐户和密码信息似乎是个不错的主意;“-

使用REST APIs,处理此问题的最佳方法是使用您的客户端(网页,移动应用程序)通过您的域或外部通过用户输入的用户凭据(在登录页面中)您将拥有一个登录/注销API来处理身份验证

当登录API进行身份验证时,它会返回一个令牌单向散列可能是用户首选项),它可以存储在客户端的加密cookie中,这样,你的客户端就不会直接处理用户凭证,令牌设置为只要你想要就过期。

对于所有后续的REST API调用,您的客户端将提交此令牌以及对API的请求(与登录/注销API不同)。 API可能会检查本地缓存(在REST服务器上)以查看这是否是有效的令牌。如果找到,则表示要求。否则,会引发错误。

如果用户在令牌过期之前注销,则登录/注销API将从本地缓存中删除此令牌,并且您的客户端需要删除会话/ cookie。

这样你的凭证永远不会在客户端传递。

当然,数据移动安全性也应该通过SSL和HTTP摘要来实现。