22

我正在构建一个将从 JavaScript 客户端使用的 PHP REST API,并且在弄清楚如何实现事物的身份验证和访问方面时遇到了一些问题。将有多个应用程序将使用我将开发的 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 中,如何让客户端了解用户的状态?

4

3 回答 3

41

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

(如果该链接不起作用 - 它已经失效一次并且必须从 archive.org 检索 - 我发现它似乎是此页面的 PDF 渲染,可在此处访问:https://www.ida。 liu.se/~TDDD97/labs/hmacarticle.pdf .)

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

于 2013-01-16T12:47:50.733 回答
8

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

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

当登录 API 进行身份验证时,它会返回一个令牌(可能是用户偏好的一种方式哈希),该令牌可以存储在客户端的加密 cookie 中。这样,您的客户端永远不会直接处理用户凭据。令牌设置为随时到期。

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

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

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

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

于 2013-11-20T03:20:03.260 回答
1

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

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

对于 JavaScript 客户端,如果缺少任何内容,请尝试https://github.com/jpillora/jquery.rest ,提交功能请求或根据需要贡献:)

于 2013-01-18T12:30:19.367 回答