欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2025/7/14 编程问答 37 豆豆
生活随笔 收集整理的这篇文章主要介绍了 深入跨域问题(2) - 利用 CORS 解决跨域 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

阅读目录:

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

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

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

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

回答问题:

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

  • 不会触发 预请求 ,因为是简单的 GET 方法。
  • 不会触发 预请求,因为是简单的 POST 方法,jquery 默认使用 application/x-www-form-urlencoded。
  • 会触发 预请求 ,虽然是 POST 方法,但是 Content-Type 为 application/json 。并非上文中的三种情况,text/plain ,multipart/form-data,application/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 方法在设置 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'); }); 复制代码

    执行结果:

  • 预请求

  • POST 请求

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

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

    总结:

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

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

    'Access-Control-Allow-Origin': '* 复制代码
  • 预请求,在服务器内,至少要设置三个 响应首部字段

    'Access-Control-Allow-Origin': ?, 'Access-Control-Allow-Methods': ?, 'Access-Control-Allow-Headers': 'Content-Type', 复制代码
  • 前端使用 content-Type: application/json 的时候,必须注意这是 预请求 ,后端需要处理 OPTIONS 方法

  • 参考与鸣谢:

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

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

    总结

    以上是生活随笔为你收集整理的深入跨域问题(2) - 利用 CORS 解决跨域的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。