Web前端开发,必须要了解的跨域解决方案

跨域

1、怎么算跨域

请求地址与当前页面访问地址中的协议、域名或IP、端口全部一致则称为同源,
若有一个不一致则不同源,也就是跨域。

2、浏览器具体是如何做到的

具体实现方式就是,XMLHttpRequest和Fetch这两个API都部署了同源限制

Web中的四种跨域的解决方案

1、JSONP
  • 原生写法
<script src="http://domain/api?param1=6&callback=jsonp"></script>
<script> 
    function jsonp(data) {
        console.log(data)
    }
</script>
  • 封装后写法
function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};
  • JSONP的具体流程

    • 第一步,网页添加一个<script>元素,向服务器请求一个脚本,这不受同源政策限制,可以跨域请求。

      <script src="http://api.foo.com?callback=bar"></script>
      

      注意,请求的脚本网址有一个callback参数(?callback=bar),用来告诉服务器,客户端的回调函数名称(bar)。

    • 第二步,服务器收到请求后,将返回的JSON 数据,放在函数名里面,最终作为字符串返回,即返回的内容就是---bar({...})

    • 第三步,客户端会将服务器返回的字符串,作为代码进行解析
      因为浏览器认为,这是<script>标签请求的脚本内容。这时,客户端只要定义了bar()函数,就能在该函数体内,拿到服务器返回的 JSON 数据。

  • JSONP跨域的原理
    利用 <script> 标签中的src属性,不受浏览器同源策略影响的特性。通过 <script> 标签中的src属性指向一个需要访问的地址,并且我们可以通过传递一个callback函数来接收并处理返回信息

  • JSONP跨域的缺陷
    只限于 get 请求

2、websocket通信

WebSocket 是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀
该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

3、CORS通信

CORS主要是服务器来实施的,在服务器端,需要在响应头中设置指定允许访问的IP/域名Access-Control-Allow-Origin),也就是让服务器告知浏览器,这个域名是否被允许访问我的资源。

浏览器通过读取这些头信息可以了解到这个跨源资源是不是应该被读取

CORS包含的响应头信息

常用响应头: 
Access-Control-Allow-Origin: <origin> | *
# 允许访问的请求头有哪些

Access-Control-Allow-Methods: <method>[, <method>]*
# 允许访问的请求方式

Access-Control-Allow-Headers: <field-name>[, <field-name>]*
# 允许添加的请求头

Access-Control-Max-Age: <delta-seconds>
# 指定了请求的结果能够被缓存多久

Access-Control-Allow-Credentials: true
# Credentials 证书,在ajax中指cookie, 这个设置为true代表发送cookie(跨域的情况)

CORS包含的请求头信息

常用请求头
Origin: <origin>
# 请求地址的origin 

Refer:<refer>
# 请求地址

Access-Control-Request-Method: <method>
# 只出现在预检请求中

Access-Control-Request-Headers: <field-name>[, <field-name>]*
# 只出现在预检请求中
4、服务器代理

跨域限制是被浏览器限制的,因此如果用服务器作为代理来请求跨域资源,就不会有这个限制了。

即浏览器端发送同源请求,服务端去发送真正的跨域请求,服务端获取返回后,再将结果返回给浏览器。

5、document.domain

利用document.domain 实现跨域的前提条件:
这种方法,只适用于同一个域名下的不同的二级域名之间,使用document.domain = '主域名' 来实现跨域)

6、iframe可通过postMessage实现跨域通信

这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息

  • 在A页面中,获取B页面的window对象,通过postMessage方法发送数据。
otherWindow.postMessage(message, targetOrigin, [transfer]);
  • 在B页面中,通过监听message事件来接收传递过来的数据。
window.addEventListener("message", function(event) {       
     console.log(event, event.data);   
}, false);

案例如下:

父窗体创建跨域iframe并发送信息

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>跨域POST消息发送</title>
    </head>
    <body>
        <textarea id="message"></textarea>
        <input type="button" value="发送" onclick="sendPost()">
        <iframe  src="http://moweide.gitcafe.io/other-domain.html" id="otherPage" style="display:none"></iframe>
    </body>
    <script type="text/JavaScript">   
	     // sendPost 通过postMessage实现跨域通信将表单信息发送到 moweide.gitcafe.io上, 并取得返回的数据   
	     function sendPost() {       
	         // 获取id为otherPage的iframe窗口对象       
	         var iframeWin = document.getElementById("otherPage").contentWindow;       
	
	         // 向该窗口发送消息       
	         iframeWin.postMessage(document.getElementById("message").value,http://moweide.gitcafe.io');   
	
	     }   
	
	     // 监听跨域请求的返回   
	     window.addEventListener("message", function(event) {       
	         console.log(event, event.data);   
	     }, false);
 </script>

</html>

子窗体接收信息并处理

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>POST Handler</title>
        <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
        <script type="text/JavaScript">
            // 监听父窗口发送过来的数据向服务器发送post请求
            window.addEventListener("message", function( event ) {
               var data = event.data;            //接收父窗口传递过来的数据
                 
               window.parent.postMessage(res, "*");      //通过postMessage给父窗口发送新的信息
            }, false);
        </script>
    </head>
    <body></body>
</html>

postmessage的参考地址:https://mp.weixin.qq.com/s?__biz=MjM5MDA2MTI1MA==&mid=2649096020&idx=2&sn=b4233a35cae5f44912b58e5ab595e6df&chksm=be5bd8f9892c51ef97072aa28ae54c70a1d3d8786629ef07ab2aa0f3fec999b12767a2582a57&scene=27

[跨域基础知识]简单请求和复杂请求(是否触发预检)

  • 简单请求
    日常开发中,可以认为满足以下三点的请求为简单请求。

    • 请求方式为 GET、POST、HEAD
    • 只有最常见的请求头
    • 比较原始的Content-Type (像application/json 就不行)

    当然这并不全面,想要知道所有条件,请去MDN中查阅。

  • 复杂请求
    简单请求之外的都是复杂请求。

  • 浏览器对于简单请求的处理过程:

    • 浏览器正常发送跨域请求,并在请求头中附加Origin字段标明请求来源。
    • 如果服务器不做出跨域的正确响应(添加Access-Control-Allow-Origin等字段),则浏览器会拦截返回的内容
    • 服务器正确响应,则一切都照常。
  • 对于复杂请求,首先会进行预请求(options), 浏览器验证服务端是否允许访问,
    若不允许,则正式请求会被浏览器在发送之前拦截。
    如果允许的话,则发送正式请求。

  • 对于简单请求,如果服务器没有配置CORS,则简单跨域请求可以成功执行
    但是返回的内容会被浏览器拦截!

作者:木子水吉_08
链接:https://www.jianshu.com/p/3d8748f85a06
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

参考链接
https://baijiahao.baidu.com/s?id=1628698007235057817&wfr=spider&for=pc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端的@font-face在问题上会遇到一些挑战。当字体文件存放在不同的名或端口上时,浏览器会默认遵循同源策略,即只有相同名、端口和协议的资源才可以被加载和使用。这就导致了在使用@font-face时,字体文件的请求会被浏览器阻止。 为了解决这个问题,可以使用nginx反向代理实现请求。通过在nginx配置中添加反向代理规则,将字体文件的请求转发到指定的服务器上,从而实现字体文件的加载。这样,在前端代码中使用@font-face时,即使字体文件存放在不同的名或端口上,也可以正常加载和使用字体效果。 同时需要注意的是,使用@font-face会增加用户流量消耗,并且在首次加载字体文件时可能会导致页面打开延迟。这是因为浏览器需要下载字体文件才能显示字体效果。但是,@font-face的好处是即使系统没有安装该字体,我们仍然可以使用它来呈现特定的字体效果。 如果你对前端的@font-face问题具体的配置和实现细节感兴趣,可以参考一些相关的网址,如W3CPlus、Stack Overflow、Dynamic Drive等。它们提供了一些关于@font-face问题的解决方案和实践经验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [解决在CSS中使用@font-face指定Web字体时,链接远程字体文件失败](https://blog.csdn.net/weixin_45400833/article/details/124338545)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [CSS3魔法堂:认识@font-face和Font Icon](https://blog.csdn.net/weixin_33722405/article/details/90150329)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值