我已经阅读了很多关于使用REST和Angular进行身份验证和授权的SO线程,但我仍然觉得我对我希望做的事情有一个很好的解决方案.对于某些背景,我打算在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最佳实践应用程序身份验证),但除非我误解了答案,否则似乎意味着应该使用服务器会话,这违反了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以进一步防止暴力攻击.
我已经积极编程已经有几年了,我刚刚回到这里.抱歉,如果我是钝的或不必要地重新发明轮子,只是希望社区根据我的阅读目前运行我的想法,看看他们是否通过了试金石.
当有人询问REST身份验证时,我会遵循Amazon Web Services并基本上建议"执行此操作".为什么?因为,从"人群的智慧"的角度来看,AWS解决了这个问题,被大量使用,经过大量分析,并且由那些比大多数人了解和关心的人更多地了解和关注什么是安全请求.安全是"不重新发明轮子"的好地方.就"肩膀站立"而言,你可以做得比AWS差.
现在,AWS不使用令牌技术,而是使用基于共享机密和有效负载的安全散列.它可以说是一个更复杂的实现(包括所有规范化过程等).
但它的确有效.
缺点是它要求您的应用程序保留人员共享密钥(即密码),并且还要求服务器可以访问密码的纯文本版本.这通常意味着密码以加密方式存储,然后根据需要进行解密.这使得服务器端的密钥管理和其他事情与安全散列技术相比更加复杂.
当然,最大的问题是任何令牌传递技术都是Man in the Middle攻击和重放攻击.SSL很自然地减轻了这些.
当然,您还应该考虑OAuth系列,它们有自己的问题,尤其是互操作性,但如果这不是主要目标,那么这些技术肯定是有效的.
对于您的应用程序,令牌租约并不是什么大问题.您的申请仍需在租约期限内运作,或能够续订.为了做到这一点,它需要保留用户凭证或重新提示它.只需将令牌视为第一类资源,就像其他任何东西一样.如果可行,请尝试将一些其他信息与请求关联,并将其捆绑到令牌(浏览器签名,IP地址),以强制执行某些位置.
你仍然对(潜在的)重播问题持开放态度,同样的请求可以发送两次.使用典型的哈希实现,时间戳是签名的一部分,它可以包含请求的生命周期.在这种情况下,这是不同的解决方案.例如,每个请求都可以使用序列ID或GUID发送,您可以记录已经播放了请求以防止再次发生请求.不同的技术.
这是一篇关于使用angular构建的身份验证和登录服务的精彩文章.
https://medium.com/opinionated-angularjs/7bbf0346acec