Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

网络安全: 非简单请求 not-simple-request 解决跨域 #31

Open
leslie1943 opened this issue Nov 20, 2020 · 0 comments
Open

网络安全: 非简单请求 not-simple-request 解决跨域 #31

leslie1943 opened this issue Nov 20, 2020 · 0 comments

Comments

@leslie1943
Copy link
Owner

如下是一个需要执行预检请求的 HTTP 请求

web端

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>跨域测试</title>
</head>

<body>
    <script>
        const req = new XMLHttpRequest()
        const url = 'https://localhost:8080/user'
        const body = JSON.stringify({ name: 'toringo' })

        function accessOtherDomain() {
            if (req) {
                req.open('POST', url, true)
                // 一个需要执行预检请求的 HTTP 请求
                req.setRequestHeader('X-PINGOTHER', 'pingpong')
                req.setRequestHeader('Content-Type', 'application/json')
                req.onreadystatechange = (e) => {
                    console.info(req.responseText)
                }
                req.send(body)
            }
        }

        accessOtherDomain()
    </script>
</body>

</html>

server端

const http = require('http');
const path = require('path');
const url = require('url');

http.createServer(function (req, res) {
  const reqUrl = url.parse(req.url, true);
  switch (reqUrl.pathname) {
    case '/user':
      let blogs = require('./blog.json');
      res.setHeader('Content-type', 'text/json; charset=utf-8');
      res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
      // 需要cookie等凭证是必须
      res.setHeader('Access-Control-Allow-Credentials', true);
      res.end(JSON.stringify(blogs));
      break;
    default:
      res.writeHead(404, 'not found');
  }
}).listen(8080, (err) => {
  if (!err) {
    console.log('8080已启动');
  }
});

执行结果
image

请求头部多了两个字段
image

上例需要成功响应数据,服务端需要改写

const http = require('http');
const path = require('path');
const url = require('url');

http.createServer(function (req, res) {
  const reqUrl = url.parse(req.url, true);
  switch (reqUrl.pathname) {
    case '/user':
      let blogs = require('./blog.json');
      res.setHeader('Content-type', 'text/json; charset=utf-8');
      res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
      // 需要cookie等凭证是必须
      res.setHeader('Access-Control-Allow-Credentials', true);

      // 新增的属性
      res.setHeader('Access-Control-Allow-Methods', 'POST, GET,OPTIONS')  // ✅✅✅ 新增的
      res.setHeader('Access-Control-Allow-Headers', 'X-PINGOTHER, Content-Type') // ✅✅✅ 新增的
      res.setHeader('Access-COntrol-Max-Age', 86400) // ✅✅✅ 新增的

      res.end(JSON.stringify(blogs));
      break;
    default:
      res.writeHead(404, 'not found');
  }
}).listen(8080, (err) => {
  if (!err) {
    console.log('8080已启动');
  }
});
 /**
          Access-Control-Allow-Origin: req.headers.origin  // 支持访问的域名
          Access-Control-Allow-Methods: POST, GET, OPTIONS:
            表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求。
            该字段与 HTTP/1.1 Allow: response header 类似,但仅限于在需要访问控制的场景中使用。这是为了避免多次"预检"请求。

          Access-Control-Allow-Headers: X-PINGOTHER, Content-Type: 
            如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
            它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

          Access-Control-Max-Age: 86400: 表明该响应的有效时间为 86400 秒,也就是 24 小时。
            在有效时间内,浏览器无须为同一请求再次发起预检请求。
            请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。
       */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant