关于ajax跨域:node-server响应头设置允许跨域却仍然存在跨域问题的解决方案

案例明天在做全栈的练习我的项目时,发现在发POST申请时,存在跨域问题(server的header设置了容许跨域),server大略如下 const express = require('express')const app = express()app.use(express.json());app.use(express.urlencoded({ extended: false }));app.post('/login', (request, response) => { //容许跨域 response.setHeader('Access-Control-Allow-Origin','*') response.setHeader('Access-Control-Allow-Headers','*'); response.send('Hello')})前端是用axios发送的ajax申请,这里会有一点影响,然而重点不在这,所以这里不贴代码。 起因剖析点开浏览器的network调试界面,发现除了post申请还有一个options申请,而后看看console里的报错信息 Access to XMLHttpRequest at 'http://127.0.0.1:8000/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. 果然发现是preflight request的问题,也就是这个options申请的跨域没有通过。 那又为什么会有这个preflight呢?参考CORS文档发现有这三种状况会发送预申请: 申请办法不是GET/POST/HEAD设置了默认申请头意外的自定义申请头POST申请中的content-type不是 application/x-www-form-urlencodedmultipart/form-datatext/plain然而咱们所用的axios发送的申请默认的content-type是application/json,所以天经地义须要去发送这个预申请,那么只须要让这个预申请跨域通过就好了 解决方案server改路由规定(post->all)最暴力的办法,间接将跨域给到all申请类型,所以预申请的options必定是可能跨域的 app.all('/login', (request, response) => { //容许跨域 response.setHeader('Access-Control-Allow-Origin','*') response.setHeader('Access-Control-Allow-Headers','*'); response.send('Hello')})增加一个options的路由规定这个就是隔靴搔痒的办法,在下方独自增加一条新的规定,应用options申请类型 app.post('/login', (request, response) => { //容许跨域 response.setHeader('Access-Control-Allow-Origin','*') response.setHeader('Access-Control-Allow-Headers','*'); response.send('Hello')})app.options('/login', (request,response) => { response.setHeader("Access-Control-Allow-Origin","*") response.setHeader("Access-Control-Allow-Headers", "*"); response.end()})

November 14, 2021 · 1 min · jiezi

关于ajax跨域:json解决跨域的实现方法及原理

先理解一下同源策略同源策略(英文全称 Same origin policy)是浏览器提供的一个平安性能MDN官网给定的概念:同源策略限度了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互这是一个用于隔离潜在歹意文件的重要平安机制 艰深的了解:浏览器规定,A 网站的 JavaScript,不容许和非同源的网站 C 之间,进行资源的交互 例如: ① 无奈读取非同源网页的 Cookie、LocalStorage 和 IndexedDB ② 无奈接触非同源网页的 DOM ③ 无奈向非同源地址发送 Ajax 申请再理解一下跨域同源指的是两个 URL 的协定、域名、端口统一,反之,则是跨域 呈现跨域的根本原因:**浏览器的同源策略**不容许非同源的 URL 之间进行资源的交互 **留神** 浏览器容许发动跨域申请,然而,跨域申请回来的数据,会被浏览器拦挡,无奈被页面获取到! 现如今,实现跨域数据申请,最次要的两种解决方案,别离是 JSONP 和 CORS。JSONP呈现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想进去的一种长期解决方案。毛病是只反对 GET 申请,不反对 POST 申请。CORS:呈现的较晚,它是 W3C 规范,属于跨域 Ajax 申请的基本解决方案。反对 GET 和 POST` 申请。毛病是不兼容某些低版本的浏览器其中:CORS次要是后盾工作人在做 个别就是应用一个两头键先截取所有的申请而后再放行 // 跨域拜访app.use((req, res, next) => { // 1. 容许那些客户端拜访 // * 代表容许所有的客户拜访我 res.header('Access-Control-Allow-Origin', '*') // 2. 容许客户端应用那些申请形式拜访我 res.header('Access-Control-Allow-Methods', 'get post,put,delete') next();})理解jsonpJSONP (JSON with Padding) 是 JSON 的一种“应用模式”,可用于解决支流浏览器的跨域数据拜访的问题。JSONP的实现原理因为浏览器同源策略的限度,网页中无奈通过 Ajax 申请非同源的接口数据。然而 <script> 标签不受浏览器同源策略的影响能够通过 src 属性,申请非同源的 js 脚本。因而,JSONP 的实现原理,就是通过 <script> 标签的 src 属性,申请跨域的数据接口,而近程服务端通过调用指定的函数并传入参数来实现传递参数 ...

July 24, 2020 · 2 min · jiezi

前端options请求解决办法

这两天遇到一个问题,发送post请求时浏览器先发送了一个options请求,给我报错了。 headers添加了token之类的自定义属性,或者Content-Type不是text/plain, multipart/form-data, application/x-www-form-urlencoded 这三个之一的话就会发送options请求。 解决办法在网上搜了好久都是叫后台处理,但是,我他妹的这个后台级别太低了,不想也不会处理这个问题。最后找到解决办法是。 解决跨域的时候使用浏览器右键->属性->目标 最后添加‘ --disable-web-security --user-data-dir’注意:引号没有,最前面有个空格。

June 15, 2019 · 1 min · jiezi

ajax跨域问题(四)

被调用方-Filter解决方案在响应头增加字段,告诉浏览器我允许对方跨域调用。所以我们可以在filter上增加相应头浏览器是先执行还是先判断?浏览器在发出请求的时候会先判断请求是简单请求还是非简单请求。如果是简单请求它就会先执行后判断,如果是非简单请求他就会先发一个预检命令,检查通过之后他才会把跨域请求发出去。浏览器如何判断?我们可以通过对比普通请求和跨域请求请求头里面的区别,对比之后发现跨域请求的请求头里面多了一个orgin字段。这个字段的值是当前域名的信息。浏览器发现这个请求是跨域请求的时候,它就会在请求头里面增加一个当前域的信息的字段。然后等请求返回回来的时候,他就会检查下响应头里面有没有允许跨域的信息如果没有他就会报错。filter代码实现简单请求和非简单请求:1、简单请求:方法为GET、HEAD、POST的请求,并且请求头(header)里面没有自定义头;Content-Type为text/plain、multipart/form-data、application/x-www-form-urlencoded。2、非简单请求:方法为PUT、DELETE的请求,发送JSON格式的ajax请求、带自定义请求头的ajax请求。例子:发送JSON格式的ajax请求Access-Control-Allow-Headers是什么?有什么作用?响应头部 Access-Control-Allow-Headers 用于 preflight request (预检请求)中,列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息。简单首部,如 simple headers、Accept、Accept-Language、Content-Language、Content-Type (只限于解析后的值为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 三种MIME类型(不包括参数)),它们始终是被支持的,不需要在这个首部特意列出。Access-Control-Max-Age是什么?浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求(比如异步请求GET, POST, PUT, DELETE, OPTIONS等等),所以浏览器会向所请求的服务器发起两次请求,第一次是浏览器使用OPTIONS方法发起一个预检请求,第二次才是真正的异步请求,第一次的预检请求获知服务器是否允许该跨域请求:如果允许,才发起第二次真实的请求;如果不允许,则拦截第二次请求。Access-Control-Max-Age用来指定本次预检请求的有效期,单位为秒,,在此期间不用发出另一条预检请求。例如:res.addHeader(“Access-Control-Max-Age”, “3600”),表示隔60分钟才发起预检请求

April 20, 2019 · 1 min · jiezi

ajax跨域问题(三)

我们解决跨域问题的重点应该是放在请求是跨域的这个角度。一个请求是怎么被处理的?当一个请求从浏览器发出去的时候他会先到中间的http服务器里面去(也叫静态服务器,主要是APACHE或者NGINX),而静态服务器接收到这个请求之后先分析这个是静态请求还是动态请求(跟用户数据有关的就是动态请求,无关的就是静态请求。例如图片,js,css都是静态请求)。如果服务器发现是静态请求的时候就会把请求直接处理然后直接返回到客户端。如果是动态请求,中间的http服务器会把请求转发到后台的应用服务器(比如TOMCAT)。应用服务器处理完之后会把请求返回给中间的http服务器,HTTP服务器再把请求转到客户端的浏览器上。这就是一个请求的完整处理过程。中间的http服务器起了两个作用:第一个是处理静态请求,第二个就是做负载均衡跨域调用的时候会有两个系统。第一个思路:被调用方改代码(基于支持跨域,修改的是被调用方的http服务器)直接从浏览器里面发出请求,请求被调用方,然后要在被调用方上面做相应的修改。这个修改是基于http协议关于跨域请求方面的规定。具体就是在返回头里面增加指定的字段,告诉浏览器我这边允许对方调用。此时浏览器就不会报跨域问题了。这种解决方案你可以在浏览器上看到被调用方的url。第二个思路:调用方解决(基于隐藏跨域,修改的是调用方的http服务器)这个时候的请求不是从浏览器发出,而是从中间的http服务器转出去的,通过服务器的转发之后,浏览器会发现所有的请求都是同一个域,它就不会报跨域问题。这是通过调用方来修改的。这种解决方案你首先在浏览器上看到调用方的url,不会看到被调用方的请求,但是最后还是会到被调用方的url。两种思路最终改的都是http服务器(APACHE或者NGINX)但是是两种不同的思路。

April 20, 2019 · 1 min · jiezi

ajax跨域问题(二)

jsonp是一个非官方协议,它是一个约定。它约定了我请求的参数里面如果包含指定的参数(默认是callback)的话这就是一个jsonp请求。工作机制:在发送请求的时候加了一个callback的参数,后台发现有callback参数就知道这是一个jsonp请求,然后他就会把返回的对象有json变为javascript,而javascript的内容就是一个函数调用。内容里,callback的值做为函数名,返回的数据作为函数的参数。普通ajax请求和jsonp请求的区别:type不一样普通ajax请求发出去type是xhr的,而jsonp请求发出去的type是script,因为不是xhr类型,所以浏览器就不会做校验。返回的类型不一样。普通的ajax请求返回的类型是json对象,而jsonp里面返回的类型是js脚本。url不同jsonp的url里面会有一个callback的参数。callback参数就是前后台之间的一个约定(参数名不是必须是callback,只要前后台保持一致就行)。jsonp的弊端:服务器需要改动代码来支持jsonp实现跨域后台服务器是需要做改动的,前后台的参数要保持一致。但是如果你要调用的接口不是自己公司的代码,那jsonp就无能无力了。只支持get方法他的原理是通过动态的创建script的方法来实现跨域。script只支持get方法发送的不是XHR请求XHR请求有很多新的特性,比如异步,各种事件,而这些jsonp都不支持。总结:我们解决跨域问题的最好方法还是要从解决请求是跨域的这个角度去解决,而不是解决请求是xhr的问题。而解决请求是跨域的思路就是之前总结的两种:一种是要服务器支持跨域,一种是在前台调用的时候隐藏跨域。

April 20, 2019 · 1 min · jiezi

前端如何通过Nginx代理做到跨域访问API接口

跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源Nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上。通过把本地一个url前缀映射到要跨域访问的web服务器上,就可以实现跨域访问。对于浏览器来说,访问的就是同源服务器上的一个url。而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器一.配置Nginx废话不多说,我们直接打开nginx.conf文件server { listen 8888; server_name 127.0.0.1; location / { proxy_pass http://127.0.0.1:5500; } location /api{ proxy_pass http://ip.taobao.com/; } }配置解释:我们在浏览器中输入 127.0.0.1:8888 自动会转发到 http://127.0.0.1:5500http://127.0.0.1:5500 是本地所指向的地址,类似于vue开的的代理npm run dev 启动的一个地址http://ip.taobao.com/ 是我们要访问的接口地址(淘宝检测ip地址来源的接口)前端ajax的url地址 这样写 http://127.0.0.1:8888/api/service/getIpInfo.php?ip=117.89.35.51,访问的url中有api nginx会自动换到所对应的location前端实列代码://新建一个html文件把以下代码放入script标签中$.ajax({ //请求淘宝检测ip地址来源的接口 url:‘http://127.0.0.1:8888/api/service/getIpInfo.php?ip=117.89.35.51’, type:‘get’, success:function(res){ console.log(res) }, error:function(err){ console.log(err) }})启动服务:我是通过vsCode的Go live插件启动了一个127.0.0.1:5500的服务,有很多同学是通过node开启的代理,都一样,然后我们在浏览器中输入127.0.0.1:8888上面nginx所配置打开浏览器network数据返回如下,说明跨域访问成功二.其它跨域解决方案1.jsonp 需要目标服务器配合一个callback函数。2.window.name+iframe 需要目标服务器响应window.name。3.html5的 postMessage+ifrme 这个也是需要目标服务器或者说是目标页面写一个postMessage,主要侧重于前端通讯。4.node.js开启本地代理,类似于vue-cli中的devServer模式,阔以方便开启代理5.CORS 需要服务器设置header :Access-Control-Allow-Origin。6.Nginx反向代理,可以不用目标服务器配合,需要Nginx服务器,用于请求转发。我个人认为4 、5 、6解决跨域问题在实际开发过程中显得更为重要三.Nginx工具以及参考资料Nginx在线配置生成工具(需要翻墙)如何提高Nginx的性能Nginx常用命令Nginx 配置简述(小胡子哥)

February 15, 2019 · 1 min · jiezi

DRF跨域后端解决之django-cors-headers

在使用django-rest-framework开发项目的时候我们总是避免不了跨域的问题,因为现在大多数的项目都是前后端分离,前后端项目部署在不同的web服务器上,因为我们是后端程序员,因此我要通过后端的程序实现跨域。当然如果前端框架是Vue的话,则可以代理服务实现跨域,我也就知道一点点,如果有兴趣,大家可以自行搜索哦。DRF后端实现跨域第三方扩展———djangocorsheaders,在介绍之前,我先介绍两个概念:同源策略、跨域同源策略同源策略/SOP(Same origin policy)是一种约定,是浏览器的一种安全机制。这里同源需要"协议+域名+端口"三者都相同,否则不能进行Ajax访问。跨域不同源之间的网站通信就是跨域。安装pip install django-cors-headers注册INSTALLED_APPS = ( ‘corsheaders’,)添加中间件MIDDLEWARE = [ ‘corsheaders.middleware.CorsMiddleware’, #最好添加至第一行]配置白名单#单个配置CORS_ORIGIN_WHITELIST =( ’ 域名’,)#正则配置:CORS_ORIGIN_REGEX_WHITELIST =(r’^(https?://)?(\w+.)?jim.com $’,)或者直接允许所有主机跨域CORS_ORIGIN_ALLOW_ALL = True 默认为False一般情况下,我们配置这些就足够,当然最为一个出名的扩展,肯定做的很完美,更多的配置,请访问:https://github.com/ottoyiu/dj…

January 25, 2019 · 1 min · jiezi