深入跨域问题(2) - 利用 CORS 解决跨域

news2024/11/15 19:39:16

目录

1.搭建跨域环境(先展示一下跨域请求的情况):

2.处理非预请求

3.处理 POST 预请求

4.总结:


1.搭建跨域环境(先展示一下跨域请求的情况):

模拟客户端请求:

<!DOCTYPE html>
<html lang="zh-CN">
<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>Ajax测试</title>
</head>
<body>
    <script src="./node_modules/jquery/dist/jquery.min.js"></script>
    <script>
        $.ajax({
            url: "http://localhost:3000",
            type: "get",
            success: function (result) {
                console.log(result);
            },
            error: function (msg) {
                console.log(msg);
            }
        })
    </script>
</body>
</html>

后文,将不再粘贴 html 代码,jquery 也可以用 npm install jquery 下载。

模拟服务器响应,新建 app.js 文件,粘贴并运行 :

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.end("{name: 'BruceLee', password: '123456'}");
        }
        
        if (request.method === 'POST') {
            response.end("true");
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});

好了,现在双击打开 html 文件,就成了:

很明显,这就是跨域报错。

2.处理非预请求

在上述两个例子中,我们说到,POST 和 GET 方法,都可以实现,非预请求。

关键代码:设置一条 响应首部字段,允许 CORS 跨域资源共享:

response.writeHead(200, {
  'Access-Control-Allow-Origin': '*
}

这里,我们设置为,所有客户端都可以访问。

完整代码:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*' // 关键代码
            });
            
            response.end("{name: 'BruceLee', password: '123456'}");
        }
        
        if (request.method === 'POST') {
            
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*' // 关键代码
            });
            
            response.end("true");
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});

前端测试代码:

$.ajax({
    url: "http://localhost:3000",
    type: "get",
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})


var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    data: JSON.stringify(data),
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})

执行结果:

 

处理 非预请求 就是这么简单,只需要在后台设置,一条 响应首部字段 即可。

注意:我们使用 POST 方法时,Jquery 默认使用的 Content-Type: application/x-www-form-urlencoded,所以不会触发预请求 !!!

事实上,不仅仅是 Jquery ,axios 等封装 Ajax 的库,都默认采用 Content-Type: application/x-www-form-urlencoded !!!

3.处理 POST 预请求

不仅仅是 POST ,所有 预请求 的处理方式都一样。

POST 方法在设置 contentType 为 application/json 时会触发预请求。

前端测试代码:

var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    data: JSON.stringify(data),
    contentType: 'application/json;charset=utf-8',
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})

注意,这里的 contentType 已经修改为 application/json ,这种情况是会触发 预请求 的 ! ! !

node 服务端代码:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });
            response.end("{name: 'BruceLee', password: '123456'}");
        }

        if (request.method === 'POST') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });

            response.end( JSON.stringify({state: true}) );
        }

        if (request.method === 'OPTIONS') {	
    		
            response.end( JSON.stringify({state: true}) );
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});

在这里,我们增加了处理 OPTIONS 方法的逻辑。

测试结果:

很明显,我们在 OPTIONS 方法内部没有设置 CORS 响应首部字段 ,所以出现跨域错误;

修改代码,关键代码:

if (request.method === 'OPTIONS') {	
    response.writeHead(200, {
        'Access-Control-Allow-Origin': '*',	 // 设置 optins 方法允许所有服务器访问 
        'Access-Control-Allow-Methods': '*', // 允许访问 POST PUT DELETE 等所有方法 
    });		
    response.end( JSON.stringify({state: true}) );
}

在 node 代码中,我们增加对 OPTIONS 的处理,并且设置允许访问, POST 方法。

修改代码后,重启服务器,并刷新 html 页面,结果为:

在这里,仍然是有问题,按照报错描述,我们应该设置 Access-Control-Allow-Headers 响应首部字段 。

关键代码:


if (request.method === 'OPTIONS') {	
    response.writeHead(200, {
        'Access-Control-Allow-Origin': '*',	 // 设置 optins 方法允许所有服务器访问 
        'Access-Control-Allow-Methods': '*', // 允许访问路径 '/' POST等所有方法
        'Access-Control-Allow-Headers': 'Content-Type',	// 允许类 Content-Type 头部 
    });	
    response.end( JSON.stringify({state: true}) );
}

 我们需要设置,允许使用头部为 Content-Type 的内容访问。

完整代码:

const http = require('http');

const server = http.createServer((request, response) => {
    if (request.url === '/') {
        if (request.method === 'GET') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });
            response.end("{name: 'BruceLee', password: '123456'}");
        }

        if (request.method === 'POST') {
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*'
            });

            response.end( JSON.stringify({state: true}) );
        }

        if (request.method === 'OPTIONS') {	
            response.writeHead(200, {
                'Access-Control-Allow-Origin': '*',	 // 设置 optins 方法允许所有服务器访问 
                'Access-Control-Allow-Methods': '*', // 允许访问路径 '/' POST等所有方法
                'Access-Control-Allow-Headers': 'Content-Type',	// 允许类 Content-Type 头部 
            });
        }
    }

    response.end('false');
});

server.listen(3000, () => {
    console.log('The server is running at http://localhost:3000');
});

执行结果:

  1. 预请求

2.POST 请求

这样就完成,对 预请求 的处理。现在你可以狠狠地告诉后台:是你没有处理 OPTIONS 方法 !!!

好了,到这里,知道了基础的 预请求 处理的解决办法了。 

4.总结:

  1. 使用 CORS 跨域资源共享,是需要分成 预请求 与 非预请求 处理的。

  2. 非预请求,在服务器内,只需要简单设置:

'Access-Control-Allow-Origin': '*

    3.预请求,在服务器内,至少要设置三个 响应首部字段

'Access-Control-Allow-Origin': ?,	  
'Access-Control-Allow-Methods': ?, 
'Access-Control-Allow-Headers': 'Content-Type',

 

4.前端使用 content-Type: application/json 的时候,必须注意这是 预请求 ,后端需要处理 OPTIONS 方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176313.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

客快物流大数据项目(一百零七):物流信息查询服务接口开发解决方案

文章目录 物流信息查询服务接口开发解决方案 一、业务需求

探究数据库mysql的vachar、test、longtext存储极限

文章目录背景介绍项目实操如果想要自己尝试&#xff0c;使用Apipost工具&#xff0c;调用接口测试即可mysql类型如果感觉有点意思点个关注&#xff0c;一键三连吧&#xff01;蟹蟹&#xff01;&#xff01;&#xff01;背景 想要清晰的了解到&#xff0c;使用longtext类型&…

C++:类的构造函数与析构函数

目录 一.前言 二.类的构造函数 1.构造函数基本概念与语法细则 2.编译器默认生成的无参构造函数和自定义构造函数 3.构造函数的特性(可重载) 4.关于构造函数的注意事项 5.构造函数的应用示例&#xff1a; 三.类的拷贝构造函数 1.拷贝构造函数基本概念 2.编译器默认生成…

零入门容器云实战之文章目录列表

建议: 1、网盘资源 零入门容器云网络实战 链接: https://pan.baidu.com/s/1nPLRkAwjItAHmtEU2T1F4g 提取码: rrpd 2、技术交流群 QQ群&#xff1a; 342498897 3、发布说明 绿色字体&#xff0c; 表示已经发布&#xff0c;可以观看 灰色字体&#xff0c; 表示未发布 发布频…

汽车研究(科普)

什么是汽车的排量&#xff0c;1.5L与2.0T又是指什么? 汽车的动力来源于燃油在气缸内爆燃产生的力&#xff0c;力推动活塞连着曲轴传到离合变速箱&#xff0c;通过后桥作用让车轮转&#xff0c;排量1.5、2.0指的就是气缸的容量&#xff0c;如果是带增压的用字母T表示&#xff0…

JQuery总结(二)

属性操作&#xff1a; 文本操作&#xff1a; <div><span>内容</span></div><input type"text" value"请输入内容"> </body> <script src"jQuery.min.js"></script> <script > console.lo…

目录 行盒的盒模型 显著特点 行块盒 空白折叠 可替换元素 和 非可替换元素 分页例子 display:inline-block object-fit

目录行盒的盒模型行盒显著特点行块盒空白折叠可替换元素 和 非可替换元素行盒的盒模型 常见的行盒&#xff1a;包含具体内容的元素 span、strong、em、i、img、video、audio 这些行盒模型也都有 content、padding、border、margin的 但它们与块盒还是有明显区别 行盒显著特…

【Leetcode面试常见题目题解】7. 删除链表的倒数第 N 个结点

前言 本文是LC第19题&#xff1a;删除链表的倒数第 N 个结点 题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 限制&#xff1a; 链表中结点的数目为 sz 1 < sz < 30 0 < Node.val < 100 1 < n < sz 进…

使用账号激活MATLAB软件

前言 很多学校购买了MATLAB软件的使用权&#xff0c;在校师生只需要使用自己的学校域名的邮箱&#xff0c;注册一个MATLAB账号即可免费使用MATLAB产品&#xff0c;再也不用各种去网上找破解资源了。 账号注册 访问账户注册页面&#xff1a; 创建 MathWorks 帐户然后填写账户信…

三、pyhon基础语法进阶篇(黑马程序猿-python学习记录)

黑马程序猿的python学习视频&#xff1a;https://www.bilibili.com/video/BV1qW4y1a7fU/ 目录 一、文件操作 一、 文件的读取 1. 打开文件open() 2. 读取文件10个字节read(10) 3. 读取文件全部信息read() 4. 读取文件readLines() 5. 读取文件readLine() 6. for循环读取…

【HTML】我用“一行“代码为CSDN博客主页挂上灯笼(附源码)

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

第一章 ArcMap、ArcCatalog、 ArcToolbox基础入门操作

文章目录第一节 ArcMap入门1 界面的基本介绍2 加载数据3 添加图层4 数据表5 内容列表5.1 按绘制顺序5.2 按源5.3 按可见性5.4 按可选性第二节 ArcCatalog入门1 界面和功能介绍2 文件夹连接3 新建数据4 修改字段第三节 ArcToolbox操作入门1 界面基本介绍2 查找工具3 查看帮助4 工…

汇编【王爽】实验8、9

实验8 分析一个奇怪的程序 程序从startstartstart入口处开始执行&#xff0c;一个nop指令占一个字节并表示No operation&#xff0c;此处用了两个nop指令的目的是在sss处预留两个字节的空间&#xff0c;程序执行mov cs:[di], ax之后sss处的两个字节被试图写入jmp short s1&…

【数据结构】二叉树的基本知识

目录前言一、树1、树的相关概念&#xff08;1&#xff09;结点&#xff08;2&#xff09;结点的度&#xff08;3&#xff09;叶结点&#xff08;4&#xff09;分支结点&#xff08;5&#xff09;父亲结点&#xff08;6&#xff09;子节点&#xff08;7&#xff09;树的度&#…

Spring笔记上(基于XML配置)

新年快乐。 文章目录一、Spring概述1. 为什么要用Spring框架&#xff1f;2. Spring介绍二、IOC/DI快速入门1. IOC控制反转2. DI依赖注入三、Bean的配置1. Bean的基础配置2. Bean的别名配置3. Bean的作用范围配置四、Bean的实例化1. 构造方法方式2. 静态工厂方式3. 实例工厂方式…

Java面试题,JVM相关问题

JVM相关问题一 、JDK、JRE、JVM二、内存管理三、GC如何判断对象可以被回收&#xff08;这是JVM的基础&#xff09;一 、JDK、JRE、JVM JDK&#xff1a;Java Development Kit【Java开发工具】&#xff0c;提供给Java开发人员来使用的。JRE&#xff1a;Java Runtime Environment…

Solid Edge 放样使用引导曲线

放样用引导曲线的时候被一个错误提示卡了挺长时间——“选来用作路径或横截面的所有边必须连接在一起”&#xff0c;所以记录一下遇到的问题。基础的操作可以去看帮助文件https://docs.sw.siemens.com/zh-CN/doc/246738425/PL20211001099989437.feature_modeling/feat12c&#…

Sprig框架集成(SSM框架) | Sping+SpringMVC+Mybatis

SSM框架 SSM是spingspringMVCmybatis集成的框架&#xff1a;标准的MVC模式&#xff0c;整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层 Spring&#xff08;业务层&#xff09; Spring就像是整个项目中装配bean的大工厂&#xff0c;在…

MySQL server options

介绍 MySQL安装部署时&#xff0c;经常会关注一些参数是否合理。其实这些参数分为两类型。环境中调整的绝大部分是引擎层方面的。服务层参数&#xff0c;就是mysqld服务启动时的参数&#xff0c;如&#xff1a;datadir&#xff0c;port&#xff0c;socket之类的的&#xff0c;…

多重背包问题——单调队列优化

一、多重背包问题 我们在之前的文章中曾经讲解过多重背包问题&#xff0c;当时我们讲解了两种方法&#xff0c;一种方法就是三重循环&#xff0c;这种方法最为朴素好想。但是这种方法的时间复杂度非常高&#xff0c;后来我们想到了二进制优化的方式。那么今天我们将再介绍一种…