Javascript AngularJS SPA和RestfulAPI服务器安全

Javascript AngularJS SPA和RestfulAPI服务器安全,javascript,angularjs,authentication,cookies,ssl,Javascript,Angularjs,Authentication,Cookies,Ssl,快速背景: 与REstful API服务器对话的完整Javascript SPA AngularJS客户端。我正在努力为API服务器制定最佳身份验证。客户机将有角色,我不关心用户是否能看到客户机上不允许的区域,因为服务器应该是气密的 身份验证流程: 用户发布用户名和密码,比如说/api/authenticate 如果有用户,服务器将生成api令牌(字段的sha散列或md5)和一些其他元数据,以确定要在1)post reply中传回的角色 令牌存储在会话cookie中(无exp、仅http、ss

快速背景:

与REstful API服务器对话的完整Javascript SPA AngularJS客户端。我正在努力为API服务器制定最佳身份验证。客户机将有角色,我不关心用户是否能看到客户机上不允许的区域,因为服务器应该是气密的

身份验证流程:

  • 用户发布用户名和密码,比如说/api/authenticate
  • 如果有用户,服务器将生成api令牌(字段的sha散列或md5)和一些其他元数据,以确定要在1)post reply中传回的角色
  • 令牌存储在会话cookie中(无exp、仅http、ssl)
  • 身份验证后的每个请求都会获取cookie中的令牌,并验证这是用户
  • 服务器上的SSL用户
问题:

  • 这是保护服务器的最佳方法吗
  • 我是否需要担心使用SSL的重播攻击?如果是这样,最好的管理方法是什么
  • 我试图想出一种使用AngularJS实现HMAC安全性的方法,但我无法在javascript客户端上存储私钥
  • 我最初使用http身份验证方法,但每次请求都发送用户名和密码似乎很奇怪

如有任何建议或示例,将不胜感激

我目前正在处理类似的情况,使用angularjs+节点作为REST API,使用HMAC进行身份验证

虽然我正处于这项工作的中间,所以我的曲调在任何时候都可能改变。这是我的想法。任何人愿意在这方面戳洞,我也欢迎:

  • 用户通过https进行身份验证、用户名和密码

  • 服务器(在我的例子中是node.js+express)向经过身份验证的用户发回一个临时通用私钥。此密钥是用户用于在HMACs客户端签名的密钥,存储在浏览器上的LocalStorage中,而不是cookie(因为我们不希望它在每个请求中来回移动)

    • 密钥存储在nodejs内存中,每六个小时重新生成一次,并记录最后生成的密钥。在密钥更改后的10秒钟内,服务器实际生成两个HMAC;一个带新钥匙,一个带旧钥匙。这样,在密钥更改时发出的请求仍然有效。如果密钥更改,服务器会将新密钥发送回客户端,以便其可以在本地存储中对其进行闪存。密钥是使用节点UUID生成的UUID的SHA256,使用加密散列。输入后,我意识到这可能无法很好地扩展,但无论如何…

  • 然后,密钥存储在浏览器上的LocalStorage中(如果在您尝试登录之前不支持LocalStorage,应用程序实际上会弹出一个“您的浏览器太旧”页面)

  • 然后,初始身份验证之外的所有请求都会发送三个自定义标头:

    • Auth Signature
      :使用本地存储的密钥签名的
      username
      +
      time
      +
      请求.body
      (在我的例子中
      request.body
      是请求变量的
      JSON.stringify()
      'd表示形式)的HMAC
    • Auth用户名
      :用户名
    • X-Microtime
      :客户端何时生成其HMAC的unix时间戳

  • 然后服务器检查
    X-Microtime
    头,如果
    X-Microtime
    now
    之间的间隔大于10秒,则将请求作为潜在的重播攻击丢弃,并抛出401

  • 然后服务器使用与客户端相同的顺序生成自己的HMAC,
    Auth Username
    +
    X-Microtime
    +
    req.body
    ,使用节点内存中的6小时私钥

  • 如果HMAC相同,则信任该请求,如果不相同,则信任401。如果我们需要处理API上特定于用户的任何内容,我们有
    Auth Username
    标题

  • 显然,所有这些通信都是通过HTTPS进行的

    编辑: 每次成功请求后,都必须将密钥返回给客户机,以使客户机保持动态密钥的最新状态。这是有问题的,因为它做的事情与cookie基本相同

    您可以将密钥设置为静态且永不更改,但这似乎不太安全,因为密钥永远不会过期。您还可以为每个用户分配一个密钥,该密钥在登录时返回给客户端,但是您仍然需要对每个请求进行用户查找,此时最好只使用基本身份验证

    编辑#2 所以,在我自己做了一些测试之后,我决定使用一个后端代理来访问仍然使用HMAC的RESTAPI

  • Angular连接到同一个域后端,后端从上面运行HMAC过程,私钥存储在此代理上。在同一个域上有这个允许我们阻止cors

  • 在成功进行身份验证时,angular只获得一个标志,我们将登录状态存储在LocalStorage中。没有密钥,但是可以识别用户并公开的东西。对我来说,这个存储值的存在决定了用户是否登录。当他们注销或我们决定使他们的“会话”无效时,我们会删除本地存储

  • 从angular到同一域代理的后续调用包含用户头。代理检查用户头(这只能由我们设置,因为我们阻止了跨站点访问),如果未设置,则返回401,否则只将请求转发到API,但HMAC希望如上所述。API将响应传递回代理,从而传递回angular

  • 这使我们能够将私有位保留在前端之外,同时仍然允许我们构建一个API,该API可以快速进行身份验证,而无需对每个请求进行DB调用,并且保持无状态。它还允许我们的API为本地移动应用程序等其他接口提供服务。移动应用程序将与私钥捆绑在一起,并为每个请求运行HMAC序列