从JavaScript客户端到REST API的授权和身份验证


Authorization and Authentication to REST API from JavaScript Client

我正在构建一个PHP REST API,将从JavaScript客户端使用,并且我有一些问题,弄清楚如何实现认证和访问方面的事情。将会有多个应用程序使用我将要开发的JavaScript库来与我的应用程序进行对话和交互。我将为他们每个人提供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中,我如何让客户端知道用户的状态?

我建议你阅读这篇关于保护RESTful API的非常好的博客文章。

(如果链接不工作—它已经死了一次,必须从archive.org—我发现它似乎是这个页面的PDF渲染在这里访问:https://www.ida.liu.se/~TDDD97/labs/hmacarticle.pdf)

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

"我开始感到困惑的是如何让这些站点上的用户对我的应用程序进行身份验证。这似乎是一个坏主意,让这个外部网站存储我的用户的帐户和密码信息; -

使用REST api,处理这个问题的最佳方法是使用您的客户端(网页,移动应用程序),无论是由您的域控制还是通过用户(在登录页面中)输入的用户凭据进行外部传递。您将有一个负责身份验证的登录/注销API。

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

对于所有后续的REST API调用,您的客户端将把这个令牌连同请求一起提交给API(这与登录/注销API不同)。API可能会检查本地缓存(在REST服务器上),以查看这是否是一个有效的令牌。如果找到,尊重请求。否则抛出错误。

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

这样您的凭据就不会在客户端传递。

当然,动态数据安全也应该通过SSL和HTTP Digest来实现。

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

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

对于JavaScript客户端,如果缺少任何东西,请尝试https://github.com/jpillora/jquery.rest,提交功能请求或贡献,如果你喜欢:)