首页 文章

在基于浏览器的应用程序中保存JWT的位置以及如何使用它

提问于
浏览
38

我'm trying to implement JWT in my authentication system and I have a few questions. To store the token, I could use cookies but it'也可以使用 localStoragesessionStorage .

哪个是最好的选择?

我已经读过JWT保护网站免受CSRF的侵害 . 但是,我无法想象假设我将JWT令牌保存在cookie存储中会如何工作 .

那么它将如何保护CSRF?

Update 1
我看到了一些如下用法示例:

curl -v -X POST -H "Authorization: Basic VE01enNFem9FZG9NRERjVEJjbXRBcWJGdTBFYTpYUU9URExINlBBOHJvUHJfSktrTHhUSTNseGNh"

当我从浏览器向服务器发出请求时,如何实现?我还看到有些人在URL中实现了令牌:

http://exmple.com?jwt=token

如果我通过AJAX发出请求,那么我可以设置一个像 jwt: [token] 的 Headers 然后我可以从 Headers 中读取标记 .

Update 2

我安装了高级REST客户端谷歌浏览器扩展,并能够将令牌作为自定义标头传递 . 在向服务器发出GET请求时,是否可以通过Javascript设置此标头数据?

3 回答

  • 9

    看看这个网站:https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

    如果要存储它们,则应使用localStorage或sessionStorage(如果可用)或cookie . 您还应该使用Authorization标头,但不使用Basic方案,而是使用Bearer one:

    curl -v -X POST -H "Authorization: Bearer YOUR_JWT_HERE"
    

    使用JS,您可以使用以下代码:

    <script type='text/javascript'>
    // define vars
    var url = 'https://...';
    
    // ajax call
    $.ajax({
        url: url,
        dataType : 'jsonp',
        beforeSend : function(xhr) {
          // set header if JWT is set
          if ($window.sessionStorage.token) {
              xhr.setRequestHeader("Authorization", "Bearer " +  $window.sessionStorage.token);
          }
    
        },
        error : function() {
          // error handler
        },
        success: function(data) {
            // success handler
        }
    });
    </script>
    
  • 78

    选择存储更多的是权衡,而不是试图找到明确的最佳选择 . 我们来看几个选项:

    选项1 - Web存储(localStorage或sessionStorage)

    优点

    • 浏览器不会自动包含从Web存储到HTTP请求的任何内容,使其容易受到CSRF的影响

    • 只能通过在创建数据的完全相同的域中运行的Javascript来访问

    • 允许使用最语义正确的方法在HTTP中传递令牌身份验证凭据(带有 Bearer 方案的 Authorization 标头)

    • 很容易挑选应该包含身份验证的请求

    缺点

    • 无法通过在创建数据的子域中运行的Javascript访问_( example.com 无法读取 example.com 所写的值)

    • ⚠️易受XSS攻击

    • 为了执行经过身份验证的请求,您只能使用允许自定义请求的浏览器/库API(在 Authorization 标头中传递令牌)

    用法

    您可以利用浏览器localStoragesessionStorage API在执行请求时存储然后检索令牌 .

    localStorage.setItem('token', 'asY-x34SfYPk'); // write
    console.log(localStorage.getItem('token')); // read
    

    选项2 - 仅HTTP的cookie

    优点

    • 这是 not 易受XSS攻击

    • 浏览器会自动在满足cookie规范的任何请求中包含令牌(域,路径和生命周期)

    • 可以在顶级域创建cookie,并将其用于子域执行的请求

    缺点

    • ⚠️它容易受到CSRF的影响

    • 您需要注意并始终考虑子域中cookie的可能用途

    • Cherry挑选应该包含cookie的请求是可行但更麻烦

    • 您可能(仍然)遇到一些问题,浏览器处理cookie的方式差异很小

    • ⚠️如果您不小心,可以实施易受XSS攻击的CSRF缓解策略

    • 服务器端需要验证cookie以进行身份验证,而不是更合适的 Authorization 标头

    用法

    您无需在客户端执行任何操作,因为浏览器会自动为您处理任何事情 .

    选项3 - 服务器端忽略Javascript可访问的cookie

    优点

    • 这是 not 易受CSRF攻击( because it's ignored by the server

    • 可以在顶级域创建cookie,并将其用于子域执行的请求

    • 允许使用最语义正确的方法在HTTP中传递令牌身份验证凭据(带有 Bearer 方案的 Authorization 标头)

    • 樱桃挑选应该包含身份验证的请求有点容易

    缺点

    • ⚠️它容易受到XSS的攻击

    • 如果您不小心设置cookie的路径,那么浏览器会在请求中自动包含cookie,这将增加不必要的开销

    • 为了执行经过身份验证的请求,您只能使用允许自定义请求的浏览器/库API(在 Authorization 标头中传递令牌)

    用法

    您可以利用浏览器document.cookie API在执行请求时存储然后检索令牌 . 此API不像Web存储那样精细(你得到了所有的cookie)所以你需要额外的工作来解析你需要的信息 .

    document.cookie = "token=asY-x34SfYPk"; // write
    console.log(document.cookie); // read
    

    附加说明

    这似乎是一个奇怪的选择,但它确实有一个很好的好处,你可以让存储可用于顶级域和所有子域,这是Web存储不会给你的东西 . 但是,实施起来更复杂 .


    结论 - 最终说明

    我的 recommendation for most common scenarios would be to go with Option 1 ,主要是因为:

    • 如果您创建Web应用程序,则需要处理XSS;始终,独立于您存储令牌的位置

    • 如果你不想担心的话

    另请注意,基于cookie的选项也大不相同,因为选项3 cookie仅用作存储机制,因此它几乎就像是客户端的实现细节 . 但是,备选方案2意味着更传统的处理身份验证的方式;有关此cookie与令牌的进一步阅读,您可能会发现这篇文章很有趣:Cookies vs Tokens: The Definitive Guide .

    最后,没有一个选项提到它,但当然必须使用HTTPS,这意味着应该适当地创建cookie以考虑到这一点 .

  • 21

    此博客文章对浏览器存储与Cookie进行了良好的并排比较,并解决了每种情况下的每次潜在攻击 . https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

    较短的答案/扰流板:cookie并在jwt中添加xsrf令牌 . 博客文章中的详细说明 .

相关问题