跨域

1. 准备工作

1.1 服务端代码

var http=require('http'); //用来启服务
//开启服务
var server=http.createServer(function(req,res){
            if(req.url === "/a"){
                res.writeHeader(200,{
                    'content-type' : 'text/html;charset="utf-8"'
                });
                res.write("接收到了请求");//将index.html显示在客户端
                res.end();
            }else{
                res.write("404");//将index.html显示在客户端
                res.end();
            }
        });
server.listen(8888); //端口号
console.log('服务器开启成功')

 

1.2 页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="jquery-3.4.1.min.js"></script>
</head>
<body>
你看到的这个页面是首页
</body>
<script>
    $.ajax({
        url:"http://localhost:8888/a",
        type:"GET",
        success:function(result){
            console.log(result);
        }});
</script>
</html>

1.3 跨域问题

 

跨域是由浏览器同源策略引起的,因为两个页面的域名或端口号不一致导致的

2. 修改浏览器解决跨域问题

打开浏览器的位置并发送桌面快捷方式

C:\Program Files (x86)\Google\Chrome\Application

 

 

修改快捷方式

目标为:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --args --disable-web-security --user-data-dir=E:\temp

目标后添加

--args --disable-web-security --user-data-dir=E:\temp

 

 

 

测试

用桌面这个修改过的浏览器打开页面

 

 

说明

这样把浏览器的跨域屏蔽后,可以获取到数据,说明跨域是浏览器造成的原因。

 

3. Jsonp解决跨域问题

3.1 Jsonp解决跨域原理

 

无论是上面那种方式访问的请求都是xhr

 

 

 

 

在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的,利用这一点,我们可以解决跨域问题

3.2 服务器端

var urlTool = require('url'); // 解析url

 

 

// 用jsonp解决跨域问题
else if (pathname === "/b"){
    var data = urlTool.parse(req.url,true).query; // 转换参数类型
    // 返回前端一个方法方法名为前面传过来的callback123,参数为括号中的JSON.stringify(data),返回到页面上会找页面是否有这个方法然后直接执行
    var str = data.callback123 + '(' + JSON.stringify(data) + ')';
    res.write(str);
    res.end();
}

 

3.3 浏览器端

3.3.1 利用ajax

// ajax利用jsonp解决跨域
$.ajax({
    url:"http://localhost:8888/b",
    type:"GET",
    dataType: "jsonp",
    jsonp: "callback123",
    data:{
        userId:"123",
        name:"linjiad",
    },
    success:function(result){
        console.log(result);
    }});

 

3.3.2 返回说明

 

3.3.3 原生

// 原生利用jsonp解决跨域
// 添加script标签
function addScript(url){
    // 创建一个script标签
    var scpt = document.createElement('script');
    // 给script标签添加src属性
    scpt.src = url;
    // 给script添加id方便以后删除
    scpt.id = "linshi";
    // 把script标签放到dom元素中
    document.body.appendChild(scpt);
}
// script标签中的方法,获取返回值的方法
function linjiad(dt){
    // 获取刚才创建的script标签
    const script = document.getElementById("linshi");
    // 删除刚才创建的script标签
    // document.body.removeChild(script);
    console.log(dt)
}
// 页面加载完成后调用添加script标签方法
window.onload=function(){
     addScript('http://localhost:8888/b?callback123=linjiad&userId=123&name=linjiad')
    // 添加方法为
    //<script src = 'http://localhost:8888/b?callback123=linjiad&userId=123&name=linjiad' />
    // 相当于添加方法为
    // <script src = linjiad({"callback123":"linjiad","userId":"123","name":"linjiad"}) />
}

3.3.4 返回说明

 

 

4 设置header解决跨域(简单请求)

4.1 不修改header情况下

4.1.1 出现问题

 

提示Access-Control-Allow-Origin

 

 

4.2 根据提示修改

修改后台代码

else if (pathname === "/c"){
    // 设置可以跨域的ip地址
    res.setHeader('Access-Control-Allow-Origin','http://localhost:63342
');
    res.write(`返回了`);
    res.end();
}

添加返回的请求头Access-Control-Allow-Origin为前端页面地址

4.3 观察结果

在返回值的请求头中存在Access-Control-Allow-Origin,并且请求成功

 

4.4 设置所有浏览器都可以访问

刚才设置的Access-Control-Allow-Origin只针对http://localhost:63342,其他地址访问依旧会存在跨域问题,所以我们修改如下

res.setHeader('Access-Control-Allow-Origin', '*');

这样所有的浏览器都可以访问该后台。

5 设置header解决跨域(复杂请求)

5.1 继续问题

给前端代码添加请求头

$.ajax({
    url:"http://localhost:8888/d",
    type:"GET",
    headers:{
      "Content-Type":"application/json",
      Accept:"application/json"
    },
    data:{
        userId:"123",
        name:"linjiad",
    },
    success:function(result){
        console.log(result);
    }});

 

结果发现又出现了了跨域问题

 

5.2 简单请求和复杂请求

简单请求

GET和POST中无自定义的请求头

Content-Type为以下几种

Text/plain

Multipart/form-data

Application/x-www-form-urlencoded

 

复杂请求

PUT

DELETE

Post请求带自定义头的ajax请求

 

简单请求和复杂请求区别

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

预检请求为OPTIONS请求,用于向服务器请求权限信息的。

预检请求被成功响应后,才会发出真实请求,携带真实数据。

 

 

5.3 修改服务端

 

根据提示修改服务端代码Access-Control-Allow-Headers

 

发现请求成功

5.4 设置自检查最大时间

res.setHeader('Access-Control-Max-Age', '3600');

 

没加之前

 

加上之后第一次

 

第二次

 

6 设置header跨域(带cookie)

6.1 给页面添加cookie

document.cookie="name=linjiad123;path=/";

 

 

 

 

path表示cookie所在的目录,默认为/,就是根目录。在同一个服务器上有目录如下:/test/,/test/cd/,/test/dd/,现设一个cookie1的path为/test/,cookie2的path为/test/cd/,那么test下的所有页面都可以访问到cookie1,而/test/和/test/dd/的子页面不能访问cookie2。这是因为cookie能让其path路径下的页面访问。

 

 

6.2 ajax请求带cookie

// 添加传输cookie
xhrFields:{
    withCredentials:true
},

查看结果

 

发现又出现了跨域问题

6.3 修改后台代码

第一步

报错位置有一段这个错误

'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'

所以把Access-Control-Allow-Origin修改为指定地址

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:63342');

 

刷新后查看页面依然报错,不过报错内容不同

 

the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true'

第二步

按照提示修改后端代码

res.setHeader('Access-Control-Allow-Credentials', true);

刷新页面查看结果

 

6.4 动态获取请求地址和header

// 获取客户端地址
var origin = req.headers.origin;
// 设置可以跨域的ip地址
res.setHeader('Access-Control-Allow-Origin', origin);

 

// 获取请求头
var header = req.rawHeaders;
// 设置允许跨域的请求头
res.setHeader('Access-Control-Allow-Headers', header);

 

7 nginx代理解决跨域问题

7.1 下载配置nginx

下载地址

http://nginx.org/en/download.html

解压

 

部署html

把之前也得页面替换到html中

 

启动nginx

 

查看

http://localhost:80

 

7.2 还原代码

把后台各种设置的header全部清空

前端页面

$.ajax({
    url:"http://localhost:8083/g",
    type:"GET",
    success:function(result){
        console.log(result);
    }});

 

后台代码

// nginx配置header
else if(pathname === "/g"){
    res.write("接收到了请求");//将index.html显示在客户端
    res.end();
}

7.3 配置nginx

 

 

 

添加include

include vhost/*.conf;

 

创建新的config

 

配置

server{

         listen 8083;

         server_name b.com;

         location /{

         proxy_pass http://localhost:8888;

         add_header 'Access-Control-Allow-Credentials' 'true';

         add_header 'Access-Control-Allow-Methods' '*';

         add_header 'Access-Control-Allow-Origin' '*';

         add_header 'Access-Control-Allow-Headers' '*';

         add_header X-Frame-Options ALLOWALL;

         }

}

 

7.4 结果查看

 

posted @ 2019-10-17 11:55  飞翔的太阳  阅读(168)  评论(0)    收藏  举报