首页 > 其他 > 详细

跨域实例和解决方案

时间:2021-04-25 00:14:00      阅读:25      评论:0      收藏:0      [点我收藏+]

跨域实例和解决方案

以下我们用 nodejs 演示了一个 http 服务, 接口为 http://localhost:8000/ .如果正常连接成功, 则会返回文本 ok .

然后以 js 在浏览器中进行 fetch 进行请求测试, 演示各种形式的跨域, 以及对应的解决方式, 所有代码都是可运行的实例.

服务端代码, 默认没有跨域

const http = require(‘http‘);
const server = http.createServer((req, res) => {
  res.writeHead(200, {
    ‘x-age‘: ‘18‘,
  });
  res.end(‘ok‘);
});
server.listen(8000, () => console.log(`启动成功 http://localhost:8000`));

客户端代码报错以及对应的设置方式

/**
简单请求
  await fetch(‘http://localhost:8000/api/test‘).then(res => res.text())
报错
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. If an opaque response serves your needs, set the request‘s mode to ‘no-cors‘ to fetch the resource with CORS disabled.
设置响应头
  ‘Access-Control-Allow-Origin‘: ‘*‘
 */

/**
自定义请求头
  await fetch(‘http://localhost:8000/api/test ‘, {
    headers: { ‘Content-Type‘: ‘application/json‘ },
  }).then(res => res.text())
错误
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
设置响应头
  ‘Access-Control-Allow-Origin‘: ‘*‘,
  ‘Access-Control-Allow-Headers‘: ‘*‘,
 */

/**
自定义方法
  await fetch(‘http://localhost:8000/api/test ‘, {
    method: ‘PATCH‘,
  }).then(res => res.text())
错误
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
设置响应头
  ‘Access-Control-Allow-Origin‘: ‘*‘,
  ‘Access-Control-Allow-Methods‘: ‘*‘,
 */


/**
携带 cookie
  await fetch(‘http://localhost:8000/api/test‘, {
    credentials: ‘include‘,
  }).then(res => res.text())
报错
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin‘ header in the response must not be the wildcard ‘*‘ when the request‘s credentials mode is ‘include‘.
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Credentials‘ header in the response is ‘‘ which must be ‘true‘ when the request‘s credentials mode is ‘include‘.
设置响应头
  ‘Access-Control-Allow-Origin‘: ‘http://localhost:9005‘,
  ‘Access-Control-Allow-Credentials‘: ‘true‘,
 */


/**
设置自定义 header
  await fetch(‘http://localhost:8000/api/test‘, {
    headers: { ‘x-age‘: ‘28‘ },
  }).then(res => res.text())
报错
  Access to fetch at ‘http://localhost:8000/api/test‘ from origin ‘http://localhost:9005‘ has been blocked by CORS policy: Request header field x-age is not allowed by Access-Control-Allow-Headers in preflight response.
设置响应头
  ‘Access-Control-Allow-Origin‘: ‘*‘,
  ‘Access-Control-Allow-Headers‘: ‘*‘,
 */


/**
读取自定义 header
  await fetch(‘http://localhost:8000/api/test‘).then(res => res.headers.get(‘x-age‘))
报错
  无, 但不能读取到 header 中的 x-age
设置响应头, 表明允许获取的自定义头
  ‘Access-Control-Allow-Origin‘: ‘*‘,
  ‘Access-Control-Expose-Headers‘: ‘x-age‘,
 */

/**
综合测试
  await fetch(‘http://localhost:8000/api/test‘, {
    method: ‘PATCH‘,
    credentials: ‘include‘,
    headers: { ‘x-age‘: ‘28‘ },
    body: JSON.stringify({
      token: ‘test_token‘,
      content: ‘test_content‘
    })
  }).then(async res => ({text: await res.text(), age: res.headers.get(‘x-age‘)}))
 */

总结

是否可以跨域, 是由服务器端决定的. 通常设置响应头即可, 在响应头中告诉浏览器允许跨域的域名, 以及允许跨域的方式, 还有允许读取和设置的请求头, 全都由服务端决定.

一般我们有几种解决方案:

  • 关闭浏览器的安全策略
  • 安装浏览器插件
  • 直接从后端代码上设置为允许
  • 使用代理方式

其中插件的方式和代理的方式其他都是在中途拦截并设置 header 为对应的跨域标致.

在前端项目的开发环境中, 一般可以使用 webpack 的 proxy 功能, 或者可以使用 mockm 的 proxy 功能. 推荐 mockm, 因为它不仅可以代理, 并且不需要复杂的配置, 还能获取到请求的接口历史和数据.

跨域实例和解决方案

原文:https://www.cnblogs.com/daysme/p/14698118.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!