使用file协议遇到跨域问题的解决方案和原理分析

 

问题描述

今天尝试用ES6的module特性,引入文件时遇到了跨域问题:

//html
<script type="module" src="./index.js">
</script>

//index.js
import{cars} from './cars.js';
const message=cars[0].make;
document.getElementById('message-element')
  .textContent=message;

//cars.js
//making a module
const carsJson=`[
   {
      "year": 2000,
      "make": "Honda",
      "model": "Accord",
      "price": 2801
   },
   {
      "make": "Nissan",
      "model": "Leaf",
      "year": 2020,
      "price": 1801
   },
   {
      "make": "Ford",
      "model": "F150",
      "year": 2020,
      "price": 19501
   },
   {
      "year": 2021,
      "make": "fwef",
      "model": "cool",
      "price": 1200
   }
]`
export const cars=JSON.parse(carsJson);

解决方案

在atom编辑器中安装了atom-live-server插件,用来在本地开一个服务器,避免了使用file协议,成功的解决了问题。

插件的安装参考了https://blog.csdn.net/Asuna_Yu/article/details/80358949

原因分析

同源策略

起初同源策略的含义是A网站设置的cookie,B网站不能打开,除非两个网站“同源”:协议相同、域名相同、端口相同。

现在,如果非同源,主要有三种行为会受到限制:

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

举一个具体的例子:你向登录购物网站A请求接口进行登录,然后A网站的服务器给你发送Set-Cookie,然后你接下来浏览网站A,再次发送请求时,浏览器就会自动将cookie附加在http请求的头字段Cookie中,服务器就知道你已经登陆过了。这时你被打断,打开了网站B(恶意网站),网站B读取了网站A的Cookie并向A的服务器发送请求,在你没有退出登录的情况下,网站B相当于登陆了你的账号。这种攻击叫做CSRF攻击。

preview

同源策略是一件保护用户信息安全的好事,但是有时我们开发的正常操作也会受到影响,如何解决?

<script> <img> <link>这些标签默认是不受到同源策略的限制的,可以跨域请求,常规的请求的Sec-Fetch-Mode域是no-cors。而ES6使用模块Module需要在script标签中指定type="module",这类使用了module的标签是受限于同源策略的,这类请求的Sec-Fetch-Mode域是cors,cors请求的request header的origin必须合法,即必须包含上面报错图中的http,data,chrome,https等协议的信息,file协议是不行的,甚至没有request header的信息。因此,在本地开启http服务器,所以正常了。

ES6标准中对于module有如下描述:

Regular <script> tags can fetch scripts on other domains but modules are fetched using cross-origin resource sharing (CORS). Modules on different domains must therefore set an appropriate HTTP header, such as Access-Control-Allow-Origin: *.

Finally, modules won’t send cookies or other header credentials unless a crossorigin="use-credentials" attribute is added to the <script> tag and the response contains the header Access-Control-Allow-Credentials: true.

也就是说module是需要通过跨域请求访问的资源,不同源的服务端需要设置Access-Control-Allow-Origin字段才可以访问。然后,为了安全,除非在<script>标记中添加了一个crossorigin =“ use-credentials”属性,并且响应包含标头Access-Control-Allow-Credentials:true,否则modules将不会发送cookie或其他标头凭证。

参考文献:

https://www.sitepoint.com/understanding-es6-modules/

 https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

https://segmentfault.com/a/1190000015597029

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 React 中使用 Axios 进行网络请求时,解决跨域问题可以通过以下方法: 1. 在后端服务器开启 CORS:在后端服务器的响应头中添加 CORS 相关的头信息,允许指定的域名进行跨域访问。可以在后端的响应中添加如下的头信息: ``` Access-Control-Allow-Origin: http://localhost:3000 // 允许访问的域名 Access-Control-Allow-Methods: GET, POST, PUT, DELETE // 允许的请求方法 Access-Control-Allow-Headers: Content-Type // 允许的请求头 ``` 请注意,在生产环境中,应该限制允许跨域访问的域名,避免安全风险。 2. 使用代理服务器:可以在开发环境中使用代理服务器来解决跨域问题。在 React 的配置文件(例如 `package.json` 或 `webpack.config.js`)中,将代理服务器的地址配置为 Axios 请求的基础路径。例如: ```javascript axios.defaults.baseURL = '/api'; // 代理服务器的地址 ``` 然后,在网络请求时,只需使用相对路径即可。 3. JSONP (仅适用于 GET 请求):如果后端支持 JSONP,可以使用 Axios 发送 JSONP 请求来避免跨域问题。通过将 `callback` 参数添加到请求 URL 中,使得响应返回一个函数调用。例如: ```javascript axios.get('http://api.example.com/data?callback=handleResponse') .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误 }); ``` 在全局作用域下定义 `handleResponse` 函数,用于处理响应数据。 以上是一些常见的解决跨域问题的方法,你可以根据你的具体情况选择适合的方法。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值