从 JavaScript 客户端对 REST API 进行授权和认证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14262271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 16:12:23  来源:igfitidea点击:

Authorization and Authentication to REST API from JavaScript Client

phpjavascriptapirestauthentication

提问by lightstrike

I'm building a PHP REST API that will be utilized from a JavaScript client, and am having some issues figuring out how to implement the auth and access side of things. There will be multiple applications that will use a JavaScript library that I'll be developing to talk and interact with my application. I'll be providing API keys to each of them, so that's not an issue.

我正在构建一个将从 JavaScript 客户端使用的 PHP REST API,并且在弄清楚如何实现身份验证和访问方面时遇到了一些问题。将有多个应用程序将使用我将开发的 JavaScript 库来与我的应用程序对话和交互。我将为他们每个人提供 API 密钥,所以这不是问题。

Where I start getting confused is how to have the users on these sites authenticate to my application. It seems like a bad idea to have this external site store my user's account and password information; so, I guess I should have my JavaScript library include a login widget that asks for the user's account info for my application.

我开始感到困惑的是如何让这些站点上的用户对我的应用程序进行身份验证。让这个外部站点存储我用户的帐户和密码信息似乎是个坏主意;所以,我想我应该让我的 JavaScript 库包含一个登录小部件,它会为我的应用程序询问用户的帐户信息。

If authentication is successful there, since I'm working with a REST API, I'll need to store the token retrieved in a client side cookie or something so that the user doesn't need to login to my application again on every page of the external site. However, what happens if the user logs out of the external site, and then another user logs in from the same browser? As far as my JavaScript library is concerned, the old user would still be logged into my application, because the cookie/token would not have expired yet - how can I clear my cookie when the previous user's session ends? Or, am I completely off the right path here?

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

So, I'm thinking the process would be something like:

所以,我认为这个过程会是这样的:

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
});

Sorry, there's several questions buried in here. I guess the main one is if I'm storing the token to a cookie, how do I ensure that it is cleared when the user logs off of the external application? Or, if I shouldn't be storing it to a cookie, how do I keep the client aware of the user's state?

抱歉,这里隐藏了几个问题。我想主要是如果我将令牌存储到 cookie 中,如何确保在用户注销外部应用程序时将其清除?或者,如果我不应该将它存储到 cookie,我如何让客户端知道用户的状态?

回答by Epoc

I suggest you to read this very good blog postabout securing a RESTful API.

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

(In case that link doesn't work—it has already gone dead once and has to be retrieved from archive.org—I found what it seems to be a PDF render of this page accessible here: https://www.ida.liu.se/~TDDD97/labs/hmacarticle.pdf.)

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

Note:my answer is off-topic because the solution provided in the blog post above is not secure from a Javascript client. In fact, it explain mostly how to secure a REST API on the server side.

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

回答by Kingz

"Where I start getting confused is how to have the users on these sites authenticate to my application. It seems like a bad idea to have this external site store my user's account and password information;"-

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

With REST APIs, the best way to handle this is to use your clients (web pages, mobile apps) whether controlled by your domain or external pass through the user credentials entered by the user (in the login page). You would have a login/logout API that takes care of authenticating.

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

When the login API authenticates, it returns a token (one way hash maybe of user preferences of whatever), that can be stored in an encrypted cookie on the client side. This way, your clients never handle the user credentials directly. The token is set to expire whenever you want.

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

For all subsequent REST API calls, your clients will submit this token along with the request to the API (which is different from the login/logout API). The API may perhaps check a local cache (on the REST Server) to see if this is a valid token. If found, honors the request. Otherwise, throws an error.

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

If the user logs out before token expiration, then the login/logout API will delete this token from the local cache, and your clients will need to delete the session/cookie.

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

This way your credentials never get passed around on the client side.

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

And of course data-in-motion security should be achieved as well by SSL and HTTP Digest.

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

回答by jpillora

If it's a private API (you have a users table) going cross-domain from another hostname to your own hostname, I agree with the above, and suggest a simple (SSL) Login/Logout at which point you can give the user (or take away) a cookies from your domain.

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

If it's a public API (anyone can get an API key for e.g.) I'd suggest use the method in the blog post from the answer above.

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

For the JavaScript client, try https://github.com/jpillora/jquery.restif anything is missing, submit feature request or contribute if you like :)

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