什么是跨域?跨域解决方法-程序员宅基地

技术标签: 网络协议  javascript  p2p  

一、为什么会出现跨域问题

       出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的。javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port。

二、什么是跨域

1.当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

2.当我们对跨域概念有一定的基础了解时,开始实操一下跨域演示吧!

    2.1目录结构

    2.2前端页面

     public/index.html

<!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>
</head>
<body>
    <button id="btn1_get">接口测试1:get请求带参数</button>
    <button id="btn2_post"> 接口测试2:post-传递普通键值对</button>
    <hr/>
    <button id="btn3_postJSON">接口测试3:post-传递json</button>
    <hr/>
    <form id="myform">
        <input type="text" name="title">
        <input type="file" name="cover">
    </form>
    <button id="btn4_formdata">接口测试4:post-传递formdata</button>
    <hr/>
    <script src="./js/axios.js"></script>
    <script>
    document.getElementById('btn1_get').addEventListener('click',() => {
        axios.get('http://localhost:3000/getapi', {params: {a:1,b:2}})
    })
    var obj = {
        "name":"abc",
        "address":{
            "a":1,
            "b":2,
            "info":"c"
        }
    }
    document.getElementById('btn2_post').addEventListener('click', () => {
        const params = new URLSearchParams();
        params.append('param1', 'value1');
        params.append('param2', 'value2');
        axios.post('http://localhost:3000/post', params, {
            headers: {"content-type":"application/x-www-form-urlencoded"}})
    })

    document.getElementById('btn3_postJSON').addEventListener('click', () => {
        axios.post('http://localhost:3000/postJSON', obj)
    })

    document.getElementById('btn4_formdata').addEventListener('click', () => {
        console.log(1)
        var fd = new FormData(document.getElementById('myform'));

        axios.post('http://localhost:3000/publish', 
            fd
        )
    })
    </script>
</body>
</html>

 2.3后端

// 实现get接口
const express = require('express')
const app = express();

app.use(express.static('public'))
// 引入bodyParse包
const bodyParser = require('body-parser')
// 使用包. 则在后续的post请求中
// 会自动加入req.body属性,这个属性中就包含了post请求所传入的参数
// 处理普通的键值对格式
// Content-Type: application/x-www-form-urlencoded
app.use(express.urlencoded())

// 处理JSON格式
// Content-Type: application/json;
app.use(express.json())

// 引入multer包
const multer = require('multer');

// 配置一下multer
// 如果本次post请求涉及文件上传,则上传到uploads这个文件夹下
// Content-Type: multipart/form-data;
var upload = multer({ dest: 'uploads/'})


// 实现接口1: get类型接口
// 返回所传入的参数,并附上上时间戳
app.get('/getapi',(req,res)=>{
    // 通过 req.query快速获取传入的参数
    console.log(req.query);
    let obj = req.query
    
    obj._t = Date.now(); 
    res.json( obj )
})

// 实现接口2:普通post 键值对
app.post('/post',(req,res)=>{
    // 希望在后端收到post传参
    console.log(req.body);

    let obj = req.body
    obj._t = Date.now();
    
    res.json(obj)
})

// 实现接口3:用来JSON格式的数据
// Content-Type: application/json;
app.post('/postJSON',(req,res)=>{
    // 希望在后端收到post传参
    console.log(req.body);
    
    // res.send('/postJSON')
    res.json( req.body )
})

// 实现接口4:接口formDate
app.post('/publish',upload.single('cover'),(req,res)=>{
    console.log('publish...')
    //upload.single('cover')
    // 这里的cover就是在页面中表单元素中的name
    // <input type="file" name="cover" />
    // 把要上传文件放在指定的目录
    console.log(req.file);
    // 其它参数,还是在req.body中找
    console.log(req.body);

    res.json({code:200,msg:'上传成功',info:req.file.path})
})

app.listen(3000,()=>{
    console.log('express应用在3000端口启动了'); 
})

代码报错演示


 三、跨域-错误原因及解决思路

3.1什么原因导致了浏览器报跨域错误

      3.1.1发起ajax请求的那个页面的地址 和 ajax接口地址 不在同一个域中。

      3.1.2跨域错误:不同源ajax请求====> 报跨域的错误。

      3.1.3浏览器向web服务器发起http请求时 ,如果同时满足以下三个条件时,就会出现跨域问题,从而导致ajax请求失败。

(1)请求响应双方url不同源。

          双方url:发出请求所在的页面 与 所请求的资源的url

          同源是指:协议相同域名相同端口相同 都相同。

以下就是不同源的:

       从http://127.0.0.1:5500/message_front/index.html 请求http://localhost:8080/getmsg

网络中不同源的请求有很多。

(2)请求类型是xhr请求。就是常说的ajax请求。不是请求图片资源,js文件,css文件等

(3)浏览器觉得不安全。跨域问题出现的基本原因是浏览器的同源策略。同源策略是一个重要的安全策略,它限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。

注意,错误是发生在浏览器端的。请求是可以正常从浏览器发到服务器端,服务器也可以处理请求,只是返回到浏览器端时出错了。

3.2解决思路

请求响应双方url不同源

    服务器代理

请求是ajax

浏览器觉得不安全 (后端还是能收到请求的)

  • 可以安装一个浏览器插件allow-control-allow-origin 绕过同源策略。
  • 用postman软件测试
  • CORS

3.2.1请求响应双方url不同源

原理

  • script的src属性可以请求外部的js文件,这个请求不是ajax,它没有跨域问题。
  • 借助 script 标签的src请求服务端上的接口。<script src="http://localhost:3000/get"。
  • 服务端的接口返回JavaScript 脚本,并附上要返回的数据。例如:res.end("fn(数据)")。

实现步骤

  • 补充script标签并设置它的src值为接口地址
  • 改造接口返回函数调用表达式,并传入数据
  • 在前端准备相应的函数

注意:

  • script标签中的src会指向一个后端接口的地址。由于script标签并不会导致跨域问题,所以这里的请求是可以正常发送和接收的。
  • 与我们之前理解的src指向某个具体的.js文件不同,我们只需要确保src所指向的地址的返回内容是js代码就行了,而不必要src直接指向某个.js文件。
  • 接口地址中返回的内容将会作为script标签的主体。

 

注意:

  • 后端接口的返回值是一个特殊的字符串: 一个刻意拼写的js函数调用语句。

 图示:

3.2.2改发JSONP

       首先前后端需要添加不同的内容,前端加上datastype:json属性,则后端express框架已经提供了一个名为jsonp的方法来处理jsonp请求:原来是res.json,要改成res.jsonp

 3.2.3  CORS

        CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

        CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10(ie8通过XDomainRequest能支持CORS)。

 首先准备一个案例,通过在被请求的路由中设置header头,可以实现跨域。

 那么这样的方法有什么意义呢?

  • 这种方案无需客户端作出任何变化(客户端不用改代码),就当跨域问题不存在一样。
  • 服务端响应的时候添加一个 Access-Control-Allow-Origin 的响应头。

又该如何使用cors

  1. 它是一个npm包,要单独下载使用 npm 包 cors
    npm i cors
  2. 当做express中的中间件,注意代码应该放在顶部

此时也许正在想jsonp vs cors 对比哪个更好呢

jsonp:

  • 不是ajax
  • 只能支持get方式
  • 兼容性好

cors:

  • 前端不需要做额外的修改,就当跨域问题不存在。
  • 是ajax
  • 支持各种方式的请求(post,get....)
  • 浏览器的支持不好(标准浏览器都支持)

持续更新中............

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_66375317/article/details/124545878

智能推荐

实用干货 | Linux常用基础命令大全(建议收藏)_chattr +s-程序员宅基地

文章浏览阅读95次。系统目录系统信息关机 (系统的关机、重启以及登出 )文件和目录文件搜索挂载一个文件系统磁盘空间用户和群组文件的权限 - 使用 "+" 设置权限,使用 "-" 用于取消文件的特殊属性 - 使用 "+" 设置权限,使用 "-" 用于取消打包和压缩文件RPM 包 - (Fedora, Redhat及类似系统)YUM 软件包升级器 - (Fedora, RedHat及类似系统)DEB 包 (Debian, Ubuntu 以及类似..._chattr +s

我离职后面试收割小米等大厂offer,附小技巧_微软 小米 offer-程序员宅基地

文章浏览阅读54次。前言众所周知,Xamarin应该是.net下的跨平台开发工具。2016年之前还处于收费状态,后被微软收购后开源。但似乎有个现象,开源后的Xamarin发展似乎有些停滞,而且维护Xamarin的团队又很固执不愿变通。社区多次建议UI层应该统一绘图引擎,而不是映射原生控件。Xamarin.Forms给人的感觉就是性能差,动画僵硬,效果不好实现。以至于谷歌的Flutter火爆之后,Xamarin社区很多人便转移阵地,你在百度搜索Xamarin,第一个关键词就是xamarin还有人用么。那么对于C#/.net_微软 小米 offer

Java体系化进阶学习图谱:java进阶路线图_java进阶图谱-程序员宅基地

文章浏览阅读199次。第一篇Linux基础学习篇目录第零章﹑计算机概论关于电脑的硬件组成部分﹐其实你可以观察你的台式机来分析一下﹐依外观来说这家伙主要可分为三部分﹐分别是∶输入单元∶包括键盘﹑鼠标﹑读卡机﹑扫描仪﹑手写板﹑触摸屏等等一堆﹔主机部分∶这个就是系统单元﹐被主机机箱保护住了﹐里面含有一堆板子﹑CPU与内存等﹔输出单元∶例如屏幕打印机等等第一章、Linux是什么与如何学习我们知道Linux这玩意儿是在计算机上面运行的﹐所以说Linux就是一组软件·问题是这个软件是操作系统还是应用程序?且Linux可_java进阶图谱

python编写程序-30分钟学会用Python编写简单程序-程序员宅基地

文章浏览阅读3.9k次,点赞2次,收藏8次。参与文末每日话题讨论,赠送异步新书异步图书君学习目标知道有序的软件开发过程的步骤。了解遵循输入、处理、输出(IPO)模式的程序,并能够以简单的方式修改它们。了解构成有效Python标识符和表达式的规则。能够理解和编写Python语句,将信息输出到屏幕,为变量赋值,获取通过键盘输入的信息,并执行计数循环。软件开发过程运行已经编写的程序很容易。较难的部分实际上是先得到一个程序。计算机是非常实在的,必须..._用python写程序

程序员如何在工作中自我增值?看完这篇彻底明白了_程序员平常能怎么增值自己?-程序员宅基地

文章浏览阅读71次。前言随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。Sentinel 具有以下特征:丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 5_程序员平常能怎么增值自己?

苹果切换输入法_落格五笔输入法苹果版下载-落格五笔输入法APP-程序员宅基地

文章浏览阅读376次。落格五笔输入法app是一款苹果五笔输入法软件。落格五笔输入法app界面清爽简洁,响应快,一点都不卡,而且落格五笔输入法app还有很多贴心的小功能,使用很方便。软件介绍落格五笔输入法app是一款手机五笔输入法。落格五笔输入法app最大的特色就是真正的实现了自定义码表输入,软件得益于立青全人工【逐字整理,精确到每一个词条的权重排序】的五笔码表,在 iOS 上用五笔打字,就!是!爽!功能介绍- 长按退格..._落格五笔

随便推点

UltraEdit设置出现异常处理_ultraedit 字符不能以utf8打开-程序员宅基地

文章浏览阅读463次。UltraEdit设置出现异常处理UltraEdit常见问题处理方式UltraEdit常见问题1、文件无法转换格式。个人最常遇到的是突然无法GBK文件无法转换成UTF-8。昨天还能用今天就不能用的那种。最是坑爹2、一些临时起意的设置,用一段时间后发现还是最初配置好用。各种卸载重装,清理注册表都没用处理方式删除C盘下相关配置文件夹C:\Users\用户名\AppData\Roaming\IDMComp\UltraEdit\。即可恢复最初配置..._ultraedit 字符不能以utf8打开

java完全自学手册pdf,附答案+考点_java练习手册pdf-程序员宅基地

文章浏览阅读151次。01 阿里面试题之MySQL之前的阿里面试题都有做总结,具体面试题内容整理成了文档,本文是针对MySQL系列的,所以下面只展示了自己第一次面试阿里时被吊打问到的一些MySQL难题请解释关系型数据库概念及主要特点?请说出关系型数据库的典型产品、特点及应用场景?请详细描述 SQL 语句分类及对应代表性关键字。什么是 MySQL 多实例,如何配置 MySQL 多实例?如何加强 MySQL 安全,请给出可行的具体措施?误操作执行了一个 drop 库 SQL 语句,如何完整恢复?详述 MySQL 主_java练习手册pdf

JavaWeb自我复习之AJAX和JSON_java利用ajax和json的demo-程序员宅基地

文章浏览阅读87次。一、AJAX1.概念:ASynchronous JavaScript And XML 异步的JavaScript 和 XML异步和同步:客户端和服务器端相互通信的基础上同步:客户端必须等待服务器端的响应,在等待的期间客户端不能做其他操作异步:客户端不需要等待服务器端的响应,在服务器处理请求的过程中,客户端可以进行其他的操作Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在与后台服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加_java利用ajax和json的demo

C++:纯虚函数与抽象类_c++虚函数与抽象类的应用-程序员宅基地

文章浏览阅读108次。纯虚函数与抽象类//每日心得:独上高楼,望尽天涯路//日期:12.24//学习内容:纯虚函数与抽象类重点:1、语法: virtual 返回值类型 函数名 (参数列表)= 0;2、当类中有了 纯虚函数 ,则这个类为 抽象类抽象类特点1、无法实例化对象2、派生类 必须重写 抽象类中的函数,否则也属于抽象类#include <iostream>using namespace std;class Base{public: virtual void func() =_c++虚函数与抽象类的应用

Vue知识小课堂第二课——vue与Velocity实现过渡和动画_vue velocity-程序员宅基地

文章浏览阅读759次。上期回顾第一课之监听窗口滑动事件以及某具体元素内部监听滑动Velocity介绍Velocity.js插件的作用Velocity.js是一个简单易用,高性能且功能丰富的轻量级JavaScript动画库,它拥有颜色动画,转换动画(transforms)、循环、缓动、SVG动画、和滚动动画等特色功能支持Chaining链式动画,当一个元素连续应用多个velocity()时,动画以队列的方式执行案例演示:第一步安装:npm install velocity-animate@beta第二步页_vue velocity

Windows server 2012 云服务器利用iis搭建网站_windows server 2012 iis 网站-程序员宅基地

文章浏览阅读1.3k次。背景前几天把原本linux的云服务器重装成win server 2012,用rdp远程连接。后来看了好多渗透教程都是自己在云服务器上搭建web,所以想试试用iis搭建个本地网站。以前弄过已经忘了,这次写个博客以后再想起来就可以看看。话不多说,进入主题。一、安装iis现在服务器仪表盘,管理->添加角色和功能在安装过程一直下一步,直到服务器角色 选中web服务器,然后一直下一步直到安装。安装后就可以在工具 选中IIS管理服务器,进入管理界面。二、网站搭建把原来的网站_windows server 2012 iis 网站

推荐文章

热门文章

相关标签