我已经阅读了很多有关认证和授权的SO线程与REST和Angular,但我仍然不觉得我有一个伟大的解决方案,我希望做的。对于一些背景,我打算在AngularJS中构建一个我想要支持的应用程序:
>有限的客人访问
>一旦验证,基于角色的访问应用程序
>通过API进行身份验证
所有对REST API的调用都需要通过SSL发生。我想做的是构建应用程序而不破坏RESTful原则,即不保持会话状态存储在服务器上。当然,无论在客户端的授权做什么都必须在服务器端加强。因为我们需要通过每个请求传递整个状态,我知道我需要传递某种令牌,以便接收REST请求的后端服务器可以验证和授权调用。
话说,我的主要问题是关于身份验证 – 这里的最佳做法是什么?看来有很多不同的方法讨论,这里只是一些我发现:
> http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html
> http://frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/
> http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
还有一个类似的问题(AngularJS best practice application authentication),但除非我误解了答案,这似乎暗示应该使用服务器会话,这是破坏RESTful原则。
我对Amazon AWS和George Reese文章的主要关注点似乎是假定消费者是一个程序,而不是一个最终用户。可以事先向程序员发出共享秘密,然后谁可以使用它来对这里的呼叫进行编码。这里不是这种情况 – 我需要从应用程序代表用户调用REST API。
这种方法足够吗?假设我有一个会话资源:
POST / api / session
为用户创建新会话
要创建会话,您需要POST一个包含“username”和“password”的JSON对象。
{ "email" : "austen@example.com","password" : "password" }
卷曲示例
curl -v -X POST --data '{"username":"austen@example.com","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json"
响应
HTTP/1.1 201 Created { "session": { "id":"520138ccfa4634be08000000","expires":"2014-03-20T17:56:28+0000" } }
状态代码
> 201 – 创建新会话
> 400 – 错误请求,JSON对象无效或缺少必需的信息
> 401 – 未经授权,请检查电子邮件/密码组合
> 403 – 访问被拒绝,禁用的帐户或许可证无效
为了清楚起见,我省略了HATEOAS的详细信息。在后端,将创建与用户相关联的新的有限持续时间会话密钥。在后续请求中,我可以将其作为HTTP标头的一部分传递:
Authorization: MyScheme 520138ccfa4634be08000000
然后,后端服务器将负责从请求中消化出来,找到相关联的用户并强制执行请求的授权规则。它应该也更新会话的过期。
如果所有这一切都发生在SSL上,我是否可以开放任何类型的攻击,我应该防范?您可以尝试猜测会话密钥并将其放置在标题中,所以我想我可以附加一个用户GUID到会话密钥,以进一步防止暴力攻击。
这是几年来,我积极编程,我只是回到这里的秋千。道歉,如果我是钝的或不必要的重塑轮子,只是希望社区这里运行我的想法,基于我的阅读,到目前为止,看看他们是否通过了石蕊的测试。感谢您提供任何帮助/建议!
现在,AWS不使用令牌技术,而是使用基于共享秘密和有效载荷的安全散列。它可以说是一个更复杂的实现(与所有的规范化过程等)。
但它的工作。
缺点是,它要求您的应用程序保留人共享秘密(即密码),它还要求服务器访问该密码的纯文本版本。这通常意味着密码被加密存储,然后适当地解密。并且邀请更多的复杂性的密钥管理和其他事情在服务器端vs安全散列技术。
最大的问题,当然,与任何令牌传递技术是人在中间的攻击,和重放攻击。 SSL自然地减轻了这些。
当然,你也应该考虑OAuth家族,它们有自己的问题,特别是互操作性,但如果这不是一个主要目标,那么这些技术肯定是有效的。
对于你的应用程序,令牌租赁不是一件大事。您的申请仍然需要在租赁期内运营,或者能够续租。为了做到这一点,它将需要保留用户凭据或重新提示他们。只是将令牌作为第一类资源,像任何其他。如果可行,尝试并与请求关联一些其他信息,并将其捆绑到令牌(浏览器签名,IP地址),只是强制执行一些地方。
您仍然可以接受(潜在的)重放问题,其中相同的请求可以发送两次。对于典型的哈希实现,时间戳是签名的一部分,可以包括请求的生命周期。这在这种情况下解决不同。例如,每个请求可以使用序列ID或GUID发送,您可以记录请求已经播放,以防止它再次发生。不同的技术。