这个问题已经在这里以一种稍微不同的形式详细地讨论过:
宁静的身份验证
但这是从服务器端解决的。让我们从客户端来看这个问题。在此之前,我们有一个重要的前奏:
Javascript加密是没有希望的
Matasano关于这方面的文章很有名,但其中包含的教训非常重要:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
总结:
中间人攻击可以简单地使用<script>函数hash_algorithm(password){lol_nope_send_it_to_me_instead(password);} > < /脚本
中间人攻击对于通过非ssl连接为任何资源提供服务的页面来说是微不足道的。
一旦你有了SSL,你就使用了真正的加密。
再加上我自己的推论:
一次成功的XSS攻击可能会导致攻击者在您的客户端浏览器上执行代码,即使您使用的是SSL——因此,即使您已经做好了所有准备,如果攻击者找到了在其他人的浏览器上执行任何javascript代码的方法,您的浏览器加密仍然可能失败。
如果您打算使用JavaScript客户端,这将使许多RESTful身份验证方案变得不可能或愚蠢。让我们看!
HTTP基本认证
首先,也是最重要的,HTTP基本认证。最简单的方案:在每个请求中传递一个名称和密码。
当然,这绝对需要SSL,因为您在每个请求中都传递了Base64(可逆)编码的名称和密码。任何在线监听的人都可以轻松地提取用户名和密码。大多数“基本认证是不安全的”的论点来自于“基于HTTP的基本认证”,这是一个糟糕的想法。
浏览器提供了内置的HTTP基本认证支持,但它很难看,你可能不应该在你的应用程序中使用它。不过,另一种选择是将用户名和密码保存在JavaScript中。
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加密是没有希望的。你可以通过把它留给浏览器的基本认证支持来减轻这种风险,但是..如前所述,丑如罪恶。
HTTP摘要认证
使用jQuery可以进行摘要身份验证吗?
一个更“安全”的认证,这是一个请求/响应哈希挑战。除了JavaScript加密是无望的,所以它只能在SSL上工作,你仍然需要在客户端缓存用户名和密码,使它比HTTP基本认证更复杂,但不更安全。
查询带有附加签名参数的认证。
另一种更“安全”的身份验证,使用nonce和定时数据加密参数(以防止重复和定时攻击)并发送。这方面最好的例子之一是OAuth 1.0协议,据我所知,这是在REST服务器上实现身份验证的一种非常出色的方式。
https://www.rfc-editor.org/rfc/rfc5849
哦,但是JavaScript没有任何OAuth 1.0客户端。为什么?
记住,JavaScript加密是没有希望的。JavaScript不能在没有SSL的情况下参与OAuth 1.0,并且您仍然必须在本地存储客户端的用户名和密码——这与摘要认证属于同一类别——它比HTTP基本认证更复杂,但并不更安全。
令牌
用户发送用户名和密码,并作为交换获得一个可用于验证请求的令牌。
这比HTTP Basic Auth稍微安全一些,因为只要用户名/密码事务完成,您就可以丢弃敏感数据。它的rest性也较差,因为令牌构成了“状态”,使服务器实现更加复杂。
SSL仍然
但问题是,您仍然必须发送初始用户名和密码才能获得令牌。敏感信息仍然会涉及到易受攻击的JavaScript。
为了保护用户的凭据,仍然需要使攻击者远离JavaScript,并且仍然需要通过网络发送用户名和密码。SSL所需。
令牌到期
执行令牌策略很常见,比如“嘿,当这个令牌存在太长时间时,丢弃它并让用户重新验证”或“我非常确定唯一允许使用这个令牌的IP地址是XXX.XXX.XXX.XXX”。这些政策中有许多都是非常好的想法。
firesheep
然而,使用无SSL令牌仍然容易受到称为“侧钻”的攻击:http://codebutler.github.io/firesheep/
攻击者无法获得用户的凭据,但他们仍然可以假装是您的用户,这可能非常糟糕。
tl;dr:通过网络发送未加密的令牌意味着攻击者可以很容易地获取这些令牌并假装是您的用户。FireSheep是一个很简单的程序。
一个单独的、更安全的区域
您正在运行的应用程序越大,就越难绝对确保它们不能注入一些改变您处理敏感数据方式的代码。你绝对信任你的CDN吗?你的广告吗?你自己的代码库?
信用卡详细信息常见,用户名和密码不常见——一些实施者将“敏感数据输入”与应用程序的其他部分分开保存在一个单独的页面上,这个页面可以尽可能严格地控制和锁定,最好是一个难以钓鱼用户的页面。
Cookie(只是表示令牌)
将身份验证令牌放在cookie中是可能的(也是常见的)。这不会改变令牌认证的任何属性,这更像是一件方便的事情。上述所有论点仍然适用。
Session(仍然只是Token)
Session Auth只是Token身份验证,但有一些差异,使它看起来有点不同:
用户从一个未经身份验证的令牌开始。
后端维护一个与用户令牌绑定的“state”对象。
令牌是在cookie中提供的。
应用程序环境将细节从您那里抽象出来。
除此之外,它与Token Auth并没有什么不同。
这甚至偏离了RESTful实现——使用状态对象,您将越来越接近有状态服务器上普通RPC的路径。
2.0
OAuth 2.0着眼于“软件A如何允许软件B访问用户X的数据,而软件B不能访问用户X的登录凭证”的问题。
实现只是用户获得令牌的标准方式,然后第三方服务就会说“是的,这个用户和这个令牌匹配,你现在可以从我们这里获得他们的一些数据。”
不过,从根本上讲,OAuth 2.0只是一个令牌协议。它展示了与其他令牌协议相同的属性-您仍然需要SSL来保护这些令牌-它只是改变了这些令牌的生成方式。
OAuth 2.0有两种方式可以帮助您:
向他人提供身份验证/信息
从其他人那里获取认证/信息
但说到底,你只是…使用令牌。
回到你的问题
因此,您要问的问题是“我应该将我的令牌存储在cookie中并让我的环境的自动会话管理来处理这些细节,还是应该将我的令牌存储在Javascript中并自己处理这些细节?”
答案是:做任何让你开心的事。
不过,关于自动会话管理的事情是,在幕后有很多神奇的事情发生。通常,自己掌控这些细节会更好。
我21岁,所以SSL是肯定的
另一个答案是:一切都使用https,否则强盗会窃取用户的密码和令牌。