使用无状态(= 无会话)身份验证时需要 CSRF 令牌?

当应用程序依赖于无状态身份验证(使用类似 HMAC 的东西)时,是否有必要使用 CSRF 保护?

例如:

  • 我们有一个单页应用程序(否则我们必须在每个链接上追加令牌: <a href="...?token=xyz">...</a>

  • 用户使用 POST /auth验证自己。验证成功后,服务器将返回一些令牌。

  • 令牌将通过 JavaScript 存储在单页应用程序中的某个变量中。

  • 此令牌将用于访问 /admin等受限 URL。

  • 令牌将始终在 HTTP Header 中传输。

  • 没有 HTTP 会话,也没有 Cookie。

据我所知,应该有(? !)不可能使用跨站点攻击,因为浏览器不会存储令牌,因此不能自动将其发送到服务器(这就是使用 Cookies/Session 时会发生的情况)。

我错过了什么吗?

65776 次浏览

我发现了一些关于 CSRF + 使用 没有 cookie 进行身份验证的信息:

  1. Https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    “因为你不依赖 cookie,所以你不需要防止跨站点请求”

  2. Http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    “如果我们采用 cookie 方式,那么确实需要使用 CSRF 来避免跨站点请求。正如您将看到的,在使用 JWT 时,我们可以忘记这一点。”
    (JWT = JsonWebToken,一种针对无状态应用程序的基于令牌的身份验证)

  3. Http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    在不冒 CSRF 漏洞风险的情况下进行身份验证的最简单方法是避免使用 cookie 来识别用户

  4. Http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    “ CSRF 最大的问题在于 cookie 完全无法防御这种类型的攻击。如果使用 Cookie 身份验证,还必须采用其他措施来防止 CSRF。您可以采取的最基本的预防措施是确保您的应用程序永远不会对 GET 请求执行任何副作用。”

还有很多页面声明,如果不使用 cookie 进行身份验证,则不需要任何 CSRF 保护。当然,您仍然可以使用 cookie 来处理其他任何事情,但是 避免在其中存储任何类似于 session_id的东西。


如果您需要记住用户,有两个选项:

  1. localStorage: 浏览器中的键值存储。即使在用户关闭浏览器窗口之后,存储的数据仍然可用。其他网站无法访问这些数据,因为每个网站都有自己的存储空间。

  2. sessionStorage: 也是浏览器中的数据存储。区别在于: 当用户关闭浏览器窗口时,数据将被删除。但是,如果你的 webapp 由多个页面组成,它仍然是有用的。所以你可以这样做:

  • 用户登录,然后将令牌存储在 sessionStorage
  • 用户单击一个链接,它加载一个新页面(= 真的链接,没有 javascript content-place)
  • 您仍然可以从 sessionStorage访问令牌
  • 要注销,您可以手动删除 sessionStorage中的令牌,或者等待用户关闭浏览器窗口,该窗口将清除所有存储的数据。

(请看这里: http://www.w3schools.com/html/html5_webstorage.asp)


有关于令牌认证的官方标准吗?

JWT (Json Web Token) : 我认为它仍然只是一个草案,但已经有很多人使用了它,而且这个概念看起来简单而安全。(IETF: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-25)
也有很多可用的框架库。只要谷歌它!

DR

如果使用 JWT 而不使用 Cookie,则无需使用 CSRF 令牌-BUT!通过在 session/localStorage 中存储 JWT,如果您的站点具有 XSS 漏洞(相当常见) ,您就可以公开您的 JWT 和用户的身份。最好向 JWT 添加一个 csrfToken键,并将 JWT 存储在一个设置了 securehttp-only属性的 cookie 中。

阅读这篇文章以获得更多信息 Https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

您可以通过包含 xsrfToken JWT 声明使这个 CSRF 保护无状态:

{ “ iss”: “ http://galaxies.com”, “ exp”: 1300819380, “望远镜”: [“探险家”,“太阳能收割机”,“卖家”], “ sub”: “ tom@andromeda.com” “ xsrfToken”: “ d9b9714c-7ac0-42e0-8696-2dae95dbc33e” }

因此,您需要将 csrfToken 存储在 localStorage/sessionStorage 中以及 JWT 本身中(存储在一个只有 http 的安全 cookie 中)。然后,对于 csrf 保护,验证 JWT 中的 csrf 令牌是否与提交的 csrf 令牌头匹配。