web-dev-qa-db-ja.com

CORSリクエストでのCookieの設定

私はこの問題に数日間取り組んでいます。 CORSリクエストにCookieを設定します。 XHRリクエストでwithCredentialsがtrueに設定されていて、サーバーが適切なヘッダーを送信している限り、ブラウザーはSet-Cookieヘッダー。しかし、私のテストではそうではありませんでした。

コード例:

index.js(Node.jsサーバー)

const http = require('http');
const fs = require('fs');

// Pretty colors

const colors = {
  purple: '\033[95m',
  orange: '\033[93m',
  blue: '\033[97m',
  underline: '\033[4m',
  bold: '\033[1m',
  reset: '\033[0m'
}

const server = http.createServer(function (req, res) {

  //Console logs to verify what's getting hit. 

  console.log(colors.purple + colors.underline + 'Hit it!' + colors.reset);
  console.log(colors.orange + colors.bold + 'url:' + colors.reset, req.url);

  if (/\/cookie/.test(req.url)) {
    console.log(colors.blue + 'We need to cook(ie) Jesse\n' + colors.reset);

    // Generate a random string in a rather convoluted way.
    var randomStr = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) + 
    Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) + 
    Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
    randomStr = new Buffer(randomStr.toString(), 'binary').toString('base64');

    // All .dev domains pointed to localhost via dnsmasq, though a hosts file
    // Update should also do the trick.
    res.writeHead(200, {
      'Set-Cookie': 'ajaxTestCookie=cookie' + randomStr + '; Domain=.example.dev; HttpOnly',
      'Access-Control-Allow-Origin': 'http://example.dev:3999',
      'Access-Control-Allow-Credentials': 'true',
      'Access-Control-Allow-Methods': 'GET, POST',
      'Access-Control-Allow-Headers': 'Content-Type, Set-Cookie, *'
    });
    return res.end('OK!');
  }

  console.log(colors.blue + 'We\'re having fun at the HTML!\n' + colors.reset);

  // Send out html file. 
  fs.readFile('./cookies.html', function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Failure to launch!');
    }
    res.end(data.toString());
  });
});

server.listen(3999);

cookies.html

<html>

<head>
  <title>Cookie Test</title>
</head>

<body>
  <button class="getCookie">Get Cookies!</button>
  <script>
    (function() {
      document.querySelector(".getCookie").addEventListener("click", function(e) {
        console.log("test");
        var req = new XMLHttpRequest();
        req.open("GET", "http://localhost:3999/cookie", true);
        req.onload = function() {
          console.log(req.responseText);
        };
        req.withCredentials = true;
        req.send();
      });
    }());
  </script>
</body>

</html>

私はFirefox Developer EditionとChromeの両方でこれをテストしてみましたが、ページに直接アクセスしない限り、Cookieは設定されません。

CORSリクエストでCookieを機能させるために欠けているものはありますか?

12
Brandon Anzaldi

すぐにはわからなかったのは、少なくともCORSリクエストで、そしておそらく(おそらく)すべてのリクエストでサーバーによって設定されたCookieがサーバーと同じドメインに制限されていることです。

index.js(Node.jsサーバー)

const http = require('http');
const fs = require('fs');

// Pretty colors

const colors = {
  purple: '\033[95m',
  orange: '\033[93m',
  blue: '\033[97m',
  underline: '\033[4m',
  bold: '\033[1m',
  reset: '\033[0m'
}

const server = http.createServer(function (req, res) {

  //Console logs to verify what's getting hit. 

  console.log(colors.purple + colors.underline + 'Hit it!' + colors.reset);
  console.log(colors.orange + colors.bold + 'url:' + colors.reset, req.url);

  if (/\/cookie/.test(req.url)) {
    console.log(colors.blue + 'We need to cook(ie) Jesse\n' + colors.reset);
    // Generate a random string in a rather convoluted way.
    var randomStr = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) + 
    Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36) + 
    Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(36);
    randomStr = new Buffer(randomStr.toString(), 'binary').toString('base64');
    // All .dev domains pointed to localhost via dnsmasq, though a hosts file
    // Update should also do the trick.
    res.writeHead(200, {
      'Set-Cookie': 'ajaxTestCookie=cookie' + randomStr + '; domain=.example.dev; HttpOnly',
      'Access-Control-Allow-Origin': 'http://example.dev:3999',
      'Access-Control-Allow-Credentials': 'true',
      'Access-Control-Allow-Methods': 'GET, POST',
      'Access-Control-Allow-Headers': 'Content-Type, Set-Cookie, *'
    });
    return res.end('OK!');
  }
  console.log(colors.blue + 'We\'re having fun at the HTML!\n' + colors.reset);
  // Send out html file. 
  fs.readFile('./cookies.html', function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Failure to launch!');
    }
    res.end(data.toString());
  });
});

server.listen(3999); // api.example.dev:3999, for example

cookies.html

<html>

<head>
  <title>Cookie Test</title>
</head>

<body>
  <button class="getCookie">Get Cookies!</button>
  <script>
    (function() {
      document.querySelector(".getCookie").addEventListener("click", function(e) {
        console.log("test");
        var req = new XMLHttpRequest();
        // Request succeeds, but cookie will not be set!
        // req.open("GET", "http://localhost:3999/cookie", true);
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        // This line, however, will work, assuming this page is on
        // the same domain, or a subdomain of the same domain. 
        // (For example test.example.dev and api.example.dev)
        // As long as the Access-Control-Allow-Origin Header is
        // properly set to allow the domain.
        req.open("GET", "http://api.example.dev:3999/cookie", true);
        req.onload = function() {
          console.log(req.responseText);
        };
        req.withCredentials = true;
        req.send();
      });
    }());
  </script>
</body>
10
Brandon Anzaldi