跨域
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
查看
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 结果查看
                    
                
                
            
        
浙公网安备 33010602011771号