认证和会话管理SPA的最佳实践
在构建使用类似的框架角,灰烬,阵营SPA风格的应用程序等什么人认为是认证和会话管理的最佳做法?我能想到的一对夫妇考虑接近问题的途径。
When building SPA style applications using frameworks like Angular, Ember, React, etc. what do people believe to be some best practices for authentication and session management? I can think of a couple of ways of considering approaching the problem.
-
与常规的Web应用程序假设API和UI,并具有相同的原始域对待它无异于认证。
Treat it no differently than authentication with a regular web application assuming the API and and UI have the same origin domain.
这可能会涉及到有一个会话cookie,服务器端的会话存储,并可能是经过验证的网络用户界面可以打获取当前用户的信息,以帮助个性化甚至可能是决定角色/客户端上的能力,一些会话API端点。服务器将仍然强制执行的规则保护访问,当然数据,用户界面将只使用这些信息来定制体验。
This would likely involve having a session cookie, server side session storage and probably some session API endpoint that the authenticated web UI can hit to get current user information to help with personalization or possibly even determining roles/abilities on the client side. The server would still enforce rules protecting access to data of course, the UI would just use this information to customize the experience.
对待它使用一个公共的API喜欢的任何第三方客户端,并与某种象征系统类似OAuth的认证。该令牌机制将使用的客户端UI向服务器API的每一个请求进行身份验证。
Treat it like any third-party client using a public API and authenticate with some sort of token system similar to OAuth. This token mechanism would used by the client UI to authenticate each and every request made to the server API.
我真的不太多这里的专家,但#1似乎是在绝大多数情况下完全够用,但我真的很想听到一些有经验的意见。
I'm not really much of an expert here but #1 seems to be completely sufficient for the vast majority of cases, but I'd really like to hear some more experienced opinions.
此问题已得到解决,在一个稍微不同的形式,篇幅,位置:
This question has been addressed, in a slightly different form, at length, here:
但是,这从服务器端地址它。让我们来看看这个从客户端。我们这样做之前,虽然,有一个重要的prelude:
But this addresses it from the server-side. Let's look at this from the client-side. Before we do that, though, there's an important prelude:
Matasano对这篇文章是有名的,但其中包含的教训是pretty重要的:
Matasano's article on this is famous, but the lessons contained therein are pretty important:
http://www.matasano.com/articles/javascript-cryptography/
要总结一下:
- 一个中间人攻击可以用平凡
&LT更换您的密码code
功能hash_algorithm(密码){lol_nope_send_it_to_me_instead(密码); }< / SCRIPT> - 一个中间人攻击是针对供应在一个非SSL连接的任何资源页面微不足道的。
- 一旦你有了SSL,你使用真实的密码反正。
脚本>
和加入我自己的推论:
- 一个成功的XSS攻击可导致攻击者在客户端的浏览器中执行code,即使你使用SSL - 所以即使你有每个舱口封舱,您的浏览器加密仍然可以失败,如果你的攻击者找到一个方法来执行在别人的浏览器的任何JavaScript code。
这使得很多RESTful的身份验证方案不可能或愚蠢的,如果你打算使用JavaScript客户端。我们看看吧!
This renders a lot of RESTful authentication schemes impossible or silly if you're intending to use a JavaScript client. Let's look!
首先,HTTP基本认证。计划的最简单的:简单地传递用户名和密码与每个请求
First and foremost, HTTP Basic Auth. The simplest of schemes: simply pass a name and password with every request.
这,当然,绝对需要SSL,因为你传递一个Base64(可逆)EN codeD名和密码的每个请求。有人听就行了可以平凡提取用户名和密码。大多数的基本身份验证是不安全的论据来自一个地方的基本身份验证通过HTTP,这是一个可怕的想法。
This, of course, absolutely requires SSL, because you're passing a Base64 (reversibly) encoded name and password with every request. Anybody listening on the line could extract username and password trivially. Most of the "Basic Auth is insecure" arguments come from a place of "Basic Auth over HTTP" which is an awful idea.
浏览器提供的烤机的HTTP基本验证支持,但它是丑陋的罪,你可能不应该将其用于您的应用程序。另一种选择,虽然是藏匿在JavaScript的用户名和密码。
The browser provides baked-in HTTP Basic Auth support, but it is ugly as sin and you probably shouldn't use it for your app. The alternative, though, is to stash username and password in JavaScript.
这是最RESTful的解决方案。服务器不需要任何国家的知识和验证与用户的每一个个体的互动。休息爱好者(主要是strawmen)坚持认为保持任何形式的状态是异端邪说,将口吐白沫,如果你认为任何其他身份验证方法。有以这种标准符合理论的好处 - 它是由Apache的支持开箱即用 - 你可以为文件,如果你的心脏所需的对象存储在受.htaccess文件保护的文件夹
This is the most RESTful solution. The server requires no knowledge of state whatsoever and authenticates every individual interaction with the user. Some REST enthusiasts (mostly strawmen) insist that maintaining any sort of state is heresy and will froth at the mouth if you think of any other authentication method. There are theoretical benefits to this sort of standards-compliance - it's supported by Apache out of the box - you could store your objects as files in folders protected by .htaccess files if your heart desired!
在问题?您缓存在客户端的用户名和密码。这给evil.ru它一个更好的裂缝 - 甚至连最基本的XSS漏洞可能导致客户端喜气洋洋他的用户名和密码邪恶的服务器。你可以尝试通过哈希和盐密码来缓解这个风险,但要记住: JavaScript的加密是无望。您可以通过留给了浏览器的基本认证支持缓解这一风险,但..其丑无比,如前面提到的。
The problem? You are caching on the client-side a username and password. This gives evil.ru a better crack at it - even the most basic of XSS vulnerabilities could result in the client beaming his username and password to an evil server. You could try to alleviate this risk by hashing and salting the password, but remember: JavaScript Crypto is Hopeless. You could alleviate this risk by leaving it up to the Browser's Basic Auth support, but.. ugly as sin, as mentioned earlier.
Digest认证瓦特/ jQuery的,这可能吗?
一个更安全的权威性,这是一个请求/响应散列挑战。除了 JavaScript的加密是无望,所以它只能通过SSL,你还有缓存在客户端的用户名和密码,使得它比HTTP基本认证更复杂,但的没有更多的安全。
A more "secure" auth, this is a request/response hash challenge. Except JavaScript Crypto is Hopeless, so it only works over SSL and you still have to cache the username and password on the client side, making it more complicated than HTTP Basic Auth but no more secure.
另一个更安全的权威性,在这里你随机数和时序数据加密参数(以防止重复和时序攻击),并发送。其中的最好的例子是的OAuth 1.0协议,这一点,据我所知,pretty stonking方式向REST服务器上完成认证。
Another more "secure" auth, where you encrypt your parameters with nonce and timing data (to protect against repeat and timing attacks) and send the. One of the best examples of this is the OAuth 1.0 protocol, which is, as far as I know, a pretty stonking way to implement authentication on a REST server.
http://tools.ietf.org/html/rfc5849
呵呵,不过目前还没有任何的OAuth 1.0客户端JavaScript的。为什么?
Oh, but there aren't any OAuth 1.0 clients for JavaScript. Why?
JavaScript的加密是无望,切记。 JavaScript不能参加的OAuth 1.0没有SSL,你仍然必须存储在客户端的用户名和密码在本地 - 这使这种在同一类别的摘要验证 - 这比HTTP基本认证更复杂,但它的没有更安全的。
JavaScript Crypto is Hopeless, remember. JavaScript can't participate in OAuth 1.0 without SSL, and you still have to store the client's username and password locally - which puts this in the same category as Digest Auth - it's more complicated than HTTP Basic Auth but it's no more secure.
用户发送的用户名和密码,并在交换获取可用于认证请求的令牌。
The user sends a username and password, and in exchange gets a token that can be used to authenticate requests.
这是略高于HTTP基本认证更安全,因为一旦用户名/密码,交易完成后,你可以放弃敏感数据。这也是REST风格的少,作为标记构成了状态,并在服务器上执行更复杂。
This is marginally more secure than HTTP Basic Auth, because as soon as the username/password transaction is complete you can discard the sensitive data. It's also less RESTful, as tokens constitute "state" and make the server implementation more complicated.
该擦不过,是你还是要发送初始用户名和密码来获得令牌。敏感信息仍然触动你compromisable的JavaScript。
The rub though, is that you still have to send that initial username and password to get a token. Sensitive information still touches your compromisable JavaScript.
要保护用户的凭据,你仍然需要保持攻击了你的JavaScript,你仍然需要通过网络发送用户名和密码。 SSL必需。
To protect your user's credentials, you still need to keep attackers out of your JavaScript, and you still need to send a username and password over the wire. SSL Required.
这是常见的强制执行像令牌政策哎,当此令牌已经存在了太久,丢弃它,使用户再次进行身份验证。或我是pretty确保允许使用此令牌的唯一的IP地址是 XXX.XXX.XXX.XXX
。许多这些政策是pretty好点子。
It's common to enforce token policies like "hey, when this token has been around too long, discard it and make the user authenticate again." or "I'm pretty sure that the only IP address allowed to use this token is XXX.XXX.XXX.XXX
". Many of these policies are pretty good ideas.
然而,使用令牌没有SSL是仍然容易受到所谓的sidejacking攻击:的http:// codebutler。 COM / firesheep /
However, using a token Without SSL is still vulnerable to an attack called 'sidejacking': http://codebutler.com/firesheep/
攻击者没有得到你的用户的凭据,但他们仍然可以pretend是你的用户,它可以是pretty坏。
The attacker doesn't get your user's credentials, but they can still pretend to be your user, which can be pretty bad.
TL;博士:通过网络发送未加密令牌意味着,攻击者可以很容易地捉住那些令牌和pretend是你的用户。 FireSheep是一个程序,使这很容易。
tl;dr: Sending unencrypted tokens over the wire means that attackers can easily nab those tokens and pretend to be your user. FireSheep is a program that makes this very easy.
在你正在运行的应用程序时,它是绝对保证,他们将不能够注入一些code,改变你如何处理敏感数据的困难。你绝对相信你的CDN?你的广告?您自己的code基?
The larger the application that you're running, the harder it is to absolutely ensure that they won't be able to inject some code that changes how you process sensitive data. Do you absolutely trust your CDN? Your advertisers? Your own code base?
通用信用卡详细信息以及用户名和密码,不常见的 - 一些实施者不断从他们的应用程序的其余部分,可以严格控制和锁定尽可能地一个页面一个单独的页面上敏感数据录入', preferably一个很难诱骗用户。
Common for credit card details and less common for username and password - some implementers keep 'sensitive data entry' on a separate page from the rest of their application, a page that can be tightly controlled and locked down as best as possible, preferably one that is difficult to phish users with.
这是可能的(普通)把身份验证令牌在Cookie中。这不会改变任何与令牌身份验证的特性,它更多的便利事情。所有的previous论点仍然适用。
It is possible (and common) to put the authentication token in a cookie. This doesn't change any of the properties of auth with the token, it's more of a convenience thing. All of the previous arguments still apply.
会话验证只是令牌认证,但有一些差异,使它看起来像一个稍微不同的事情:
Session Auth is just Token authentication, but with a few differences that make it seem like a slightly different thing:
- 的用户开始使用未经身份验证的令牌。
- 后端认为被绑定到用户的令牌。 一个国家的对象
- 令牌处于一个cookie提供。
- 的应用环境,从你提取的细节了。
- Users start with an unauthenticated token.
- The backend maintains a 'state' object that is tied to a user's token.
- The token is provided in a cookie.
- The application environment abstracts the details away from you.
除此之外,虽然,这是一个从令牌验证没有什么不同,真的。
Aside from that, though, it's no different from Token Auth, really.
此徘徊,甚至进一步从REST风格的实现 - 与状态的对象你越走越下去纯醇'RPC的状态服务器上的路径。
This wanders even further from a RESTful implementation - with state objects you're going further and further down the path of plain ol' RPC on a stateful server.
OAuth 2.0用户看的问题,如何软件一个给软件B分别接入,而无需访问用户X的登录凭据软件B的用户X的数据。
OAuth 2.0 looks at the problem of "How does Software A give Software B access to User X's data without Software B having access to User X's login credentials."
实现非常简单,只是为用户获得令牌,然后第三方服务去是的,这个用户和这个令牌匹配的标准方式,你可以从我们现在得到他们的一些数据。
The implementation is very much just a standard way for a user to get a token, and then for a third party service to go "yep, this user and this token match, and you can get some of their data from us now."
从根本上说,虽然OAuth 2.0用户仅仅是象征性的协议。它具有相同的属性其他令牌协议 - 你仍然需要SSL来保护这些令牌 - 它只是改变了这些令牌是如何生成的。
Fundamentally, though, OAuth 2.0 is just a token protocol. It exhibits the same properties as other token protocols - you still need SSL to protect those tokens - it just changes up how those tokens are generated.
有两种方式的OAuth 2.0可以帮助您:
There are two ways that OAuth 2.0 can help you:
- 提供身份验证/信息到其他
- 获取认证/从其他信息
但是,当它发生的时候,你只是......使用令牌。
But when it comes down to it, you're just... using tokens.
所以,你问的问题是我应该保存我的令牌的cookie,并有我的环境的自动会话管理采取的细节问题,或者我应该保存我的Javascript令牌和处理这些细节我自己?
So, the question that you're asking is "should I store my token in a cookie and have my environment's automatic session management take care of the details, or should I store my token in Javascript and handle those details myself?"
答案是:做任何让你开心的。
有关自动会话管理的东西,虽然是有很多神奇发生的场景在你身后。通常它是更好是在这些细节你自己控制。
The thing about automatic session management, though, is that there's a lot of magic happening behind the scenes for you. Often it's nicer to be in control of those details yourself.
其他答案是:使用HTTPS的一切或强盗会盗取用户的密码和令牌
The other answer is: Use https for everything or brigands will steal your users' passwords and tokens.