阅读目录:

深入跨域问题(1) - 初识 CORS 跨域资源共享;

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

深入跨域问题(3) - 利用 JSONP 解决跨域

深入跨域问题(4) - 利用 代理服务器 解决跨域

回答问题:

在阅读这篇文章之前,读读第一篇文章,效果会更好!!!回答上一篇文章的问题:

  1. 不会触发 预请求 ,因为是简单的 GET 方法。
  2. 不会触发 预请求,因为是简单的 POST 方法,jquery 默认使用 application/x-www-form-urlencoded
  3. 会触发 预请求 ,虽然是 POST 方法,但是 Content-Typeapplication/json 。并非上文中的三种情况,text/plainmultipart/form-dataapplication/x-www-form-urlencoded

第三点,是最重要的一点,也是经常出错的一点,记住触发预请求三种情况 !!!

搭建跨域环境:

模拟客户端请求:

<!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 文件,就成了:

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

处理非预请求

在上述两个例子中,我们说到,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 !!!

处理 POST 预请求

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

POST 方法在设置 contentTypeapplication/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 方法 !!!

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

总结:

  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 方法

参考与鸣谢:

  • 跨域资源共享 CORS 详解 阮一峰;
  • 浏览器同源政策及其规避方法 阮一峰;
  • HTTP访问控制 (CORS) MDN 文档;

祝大家编码愉快,喜欢的话点个赞再走呗!!!

深入跨域问题(2) - 利用 CORS 解决跨域相关推荐

  1. Springboot 利用CORS 解决跨域问题

    什么是跨域 首先我们先用springboot 建立1个简单的API, 它返回1个json package com.example.demo_api_cors.controller;import com ...

  2. 【javaWeb微服务架构项目——乐优商城day03】——(搭建后台管理前端,Vuetify框架,使用域名访问本地项目,实现商品分类查询,cors解决跨域,品牌的查询)

    乐优商城day03 0.学习目标 1.搭建后台管理前端 1.1.导入已有资源 1.2.安装依赖 1.3.运行一下看看 1.4.目录结构 1.5.调用关系 2.Vuetify框架 2.1.为什么要学习U ...

  3. JAVA商城项目(微服务框架)——第7天nginx+cors解决跨域+品牌+分类查询

    0.学习目标 使用资料搭建后台系统 会使用nginx进行反向代理 实现商品分类查询功能 掌握cors解决跨域 实现品牌查询功能 1.搭建后台管理前端 1.1.导入已有资源 后台项目相对复杂,我们不再从 ...

  4. 微服务架构(5):nginx反向代理cors解决跨域

    微服务架构(5):nginx反向代理&&cors解决跨域 学习目标 1.使用域名访问本地项目 1.1.统一环境 1.2.域名解析 1.3.解决域名解析问题 1.4.nginx解决端口问 ...

  5. Cors解决跨域问题

    问题 问题:axios请求,出现两次request,其中一次Request Method: OPTIONS 原因:跨域原因 跨域问题 什么是跨域 跨域是指跨域名访问,一下情况都属于跨域: 跨域原因说明 ...

  6. 利用axios解决跨域的问题

    利用axios解决跨域的问题 参考文章: (1)利用axios解决跨域的问题 (2)https://www.cnblogs.com/Irelia/p/9972990.html 备忘一下.

  7. cors跨域_Spring Boot 中通过 CORS 解决跨域问题

    (给ImportNew加星标,提高Java技能) 转自:江南一点雨 今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的, ...

  8. 后端CORS解决跨域问题

    后端CORS解决跨域问题 参考文章: (1)后端CORS解决跨域问题 (2)https://www.cnblogs.com/zmc940317/p/10164775.html 备忘一下.

  9. 如何使用CORS解决跨域问题

    如何使用CORS解决跨域问题 参考文章: (1)如何使用CORS解决跨域问题 (2)https://www.cnblogs.com/cui-ting/p/11222579.html 备忘一下.

最新文章

  1. Java Web之XML基础
  2. java 数组 包含_Java中高效的判断数组中某个元素是否存在详解
  3. ffmpeg的map参数
  4. Cordova工程里android平台相关的index.html是怎么加载的
  5. shell执行perl_【编程技巧(一)】在Perl、Shell和Python中传参与输出帮助文档
  6. error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/r
  7. [Extjs 4] 类系统
  8. maven的基础入门
  9. 如何防范电改下分布式光伏的风险
  10. 1433抓鸡的原理详解以及防范
  11. linux艺术字体,Linux字体美化实战(Fontconfig配置)
  12. adams功能区不显示_百科Esri大赛获奖作品分享:融合OSM道路网和百度POI数据的城市功能区识别...
  13. rstudio导入txt文件_R语言 | 读写txt、csv、excel文件
  14. 联发科mt8516价格_揭秘联发科MT8516单颗芯片破千万背后的故事
  15. 百度和今日头条正式开战
  16. 金彩教育:详情页产品描述怎么写
  17. 贝叶斯算法-情感分类
  18. Creo/ProE自定义零件外观库保存使用
  19. SQLServer中使用between查询日期
  20. 活动预告丨易盾CTO朱浩齐将出席2018 AIIA大会,分享《人工智能在内容安全的应用实践》...

热门文章

  1. angular 兼容ie7 bootstrap2兼容ie6
  2. Windows多线程编程总结
  3. ExtJs十三(ExtJs Mvc图片管理之三)
  4. 使用Windows Server Backup备份恢复Exchange Server 2010数据库
  5. 利用libswscale转换yuyv422到yuv422p或rgb之间的转换, 视频翻转
  6. SQL Server LOWER Functions
  7. [转]文件IO详解(二)---文件描述符(fd)和inode号的关系
  8. Oracle归档已满的处理办法
  9. cocos2dx中的用户数据的管理
  10. c# 文件IO操作 StreamReader StreamWriter Split 使用