跨域问题总结

目录

目录

1、为什么会产生跨域

2、怎么解决跨域

1)使用jsonp。

2)cors跨域资源共享

3)使用 websocket 协议

4)使用服务器来代理跨域的访问请求,

5)前端跨域方法:使用vue

6)iframe嵌套通讯,postmessage



1、为什么会产生跨域

答:由于浏览器为了安全考虑,就会产生一个同源策略,不是一个地方出来的是不允许交互的。同源指的是协议相同、域名相同、端口号相同。因为浏览器的同源策略,就会产生跨域。解决跨域的方法有很多。我们可以根据我们 想要实现的目的来划分。

2、怎么解决跨域

1.首先我们如果只是想要实现主域名下的不同子域名的跨域操作,我们可以使用设置 document.domain 来解决。

(1)Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。如a.example.com和b.example.com。此时两个网站都设置 document.domain = "example.com", 那么两个网页就可以共享Cookie了。

2、如果是像解决 ajax 无法提交跨域请求的问题,我们可以使用 jsonp、cors、websocket 协议、服务器代理来解决问题。

1)使用jsonp

JSONP实现跨域请求的原理:简单的说,就是动态创建

​ JSONP 由两部分组成:回调函数 和 数据。回调函数是用来处理服务器端返回的数据,回调函数的名字一般是在请求中指定的。而数据就是我们需要获取的数据,也就是服务器端的数据。

工作流程:

向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

就是在json字符串外面包上一个:参数名称+左右括弧!
jsonpCallback([{“ID”:1,“Name”:“张三”},{“ID”:2,“Name”:“李四”}])

json是目的,jsonp是手段

为什么jsonp只能支持get?

JSONP 是一种【请求一段 JS 脚本,把执行这段脚本的结果当做数据】的玩法。 JSONP 库的源码就知道,常见的实现代码其实就是 document.createElement(‘script’) 生成一个 script 标签,然后插 body 里而已。在这里根本没有设置请求格式的余地)。

所以JSONP的实现原理就是创建一个script标签, 再把需要请求的api地址放到src里. 这个请求只能用GET方法, 不可能是POST

JSONP的简单实现过程

(1)如果 a.com/abc.html 想得到 b.com/1.txt 中的数据,首先在abc.html中创建一个回调函数handleResponse,用来处理服务器端返回的数据。
(2)然后在abc.html中创建一个函数 foo,该函数的功能是动态添加

a.com/abc.html的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JSONP实现跨域</title>
    <script type="text/javascript">
        function handleResponse(response){   //处理服务器返回的数据
            console.log(response);    //控制台输出
        }
        function foo() {
            var script = document.createElement("script");
            script.src = "http://192.168.31.122/1.txt"; //设置请求的链接以及处理返回数据的回调函数
            document.body.insertBefore(script, document.body.firstChild);
        }
    </script>
</head>
<body>
<button id="btn" onclick="foo()">确定</button>
</body>
</html>

192.168.10.14/1.txt 的代码,设置回调函数,数据以JSON格式存放

handleResponse([ { "name":"xie",
    "sex" :"man",
    "id" : "66" },
  { "name":"xiao",
    "sex" :"woman",
    "id" : "88" },
  { "name":"hong",
    "sex" :"woman",
    "id" : "77" }]
)

2)cors跨域资源共享

CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,因此我们只需要在服务器端配置就行。只需要后端在响应头设置Access-Control-Allow-Origin: *, * 为任意Origin,也可以指定Origin。

CORS请求的过程如下:

首先判断是不是简单请求 请求方式:HEAD,GET,POST

  • 请求头信息:

    Accept

    Accept-Language

    Content-Language

    Last-Event-ID

    Content-Type 对应的值是以下三个中的任意一个

    application/x-www-form-urlencoded
      multipart/form-data
      text/plain

只有同时满足以上两个条件时,才是简单请求,否则为非简单请求 (get.post.head) 如果是,只需要在HTTP Response后添加Access-Control-Allow-Origin;

如果不是简单请求,这个时候浏览器会分2次进行请求:一次是预检请求preflight(method: OPTIONS),主要用于检测请求来源是否合法,并返回Header。第二次才是真正的请求,所以服务器必须处理OPTIONS应答。

服务器处理请求解析如下:

(1)首先检测Http头部中是否有origin字段信息
(2)如果没有或者不被允许,则当做普通请求处理,结束;
(3)如果有并且是在允许范围内,则判断是否是复杂请求
(4)如果是复杂请求,则先执行预检请求preflight(method: OPTIONS),返回Allow-Headers、Allow-Methods等,内容为空;进如步骤6
(5)如果是简单请求,则直接进步步骤6
(6)执行请求,返回Allow-Origin、Allow-Credentials等,并返回正常内容。 

​ 例子:如果a.com想要获取b.com里的数据。

​ 答:在b.com里面添加响应头声明允许a.com的访问,代码

Access-Control-Allow-Origin: http://a.com

然后a.com就可以用ajax获取b.com里的数据了。

cors字段

(1)Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。
    注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

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

(3)Access-Control-Allow-Credentials:该字段与简单请求时的含义相同。

(4)Access-Control-Max-Age:该字段可选,用来指定本次预检请求的有效期,单位为秒。
    上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

3)使用 websocket 协议

这个协议没有同源限制。 不使用http协议,而是用自定义协议。这种协议为快速传送小数据设计。

4)使用服务器来代理跨域的访问请求

想要跨域访问其他域下的资源,需要绕开浏览器的这个限制,可以在服务器端设置一个代理,由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制。

1、在localhost:81/a.html中,向同源下的某个代理程序发出请求

$.ajax({
    url:'/proxy.php?name=hello&info=information',   //服务器端的代理程序
    type:'GET',
    success:function (){}

})

2、在代理程序proxy.php中,向非同源下的服务器发出请求,获得请求结果,将结果返回给前端。

<?php 

$name=$_GET['name'];
$info = $_GET['info'];
$crossUrl = 'http://b.com/sub?name='.$name;   //向其他域下发出请求
$res = file_get_contents($crossUrl);
echo $res; 


 ?>

就是有跨域的请求操作时发送请求给后端,让后端代为请求,然后最后将获取的结果发返回。

5)前端跨域方法:使用vue

可以自己设置一个代理服务器,找到config文件下->index.js文件,修改proxyTable中的target的值。

module.exports = {
  dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': { // 匹配所有以 '/api'开头的请求路径
        target: 'http://localhost:4000', // 代理目标的基础路径
        changeOrigin: true, // 支持跨域
        pathRewrite: {// 重写路径: 去掉路径中开头的'/api'
          '^/api': ''
        }
      }
    }

6)iframe嵌套通讯,postmessage

HTML5引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。

如何http异步请求https的跨域问题

在https页面通过post的方式向http页面提交表单是没有问题的
直接的办法就是在页面加一个隐藏的form,然后自动触发提交表单。可以在新窗口提交,或者从当前页面提交,然后在通过服务器端跳转回来。
间接实现了在https页面调用http接口的需求,由前端在html页面中添加meta:强制转换

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值