相关前台跨域的解决方式(代码片段)

lidedong lidedong     2022-12-28     745

关键词:


title: 前端跨域处理方式
date: 2018-07-08 00:37:29
categories:

  • Web
  • 前端

tags:

  • 跨域
  • cors

关于跨域请求解觉方案问题

关于浏览器跨域问题,项目中也遇到了,看了项目上一些代码的处理方式,感觉存在不少不大完善的地方,因此对于跨域,想好好梳理一下,但是最近一直在忙,因此周六抽出一天的时间了学习消化做了写笔记。

跨域的概念

跨域和同源问题

跨域实质就是跨域名、跨端口、跨协议。

同源就是同域名、同端口、同协议。

假如一个网址是  http://baidu.com:8080?user=name&pwd=password
http://   是协议   
baidu.com  是域名(注意:前面加上“wwww”即www.baidu.com不是域名)
8080  是端口    
user=name&pwd=password   是地址带的参数

引用地址 https://www.cnblogs.com/shirly77/p/6440635.html?utm_source=itdadao&utm_medium=referral

跨域的解决方法

跨域的解决方式主要有以下几种方式:1.jsonp(局限性比较大,缺点比较多,下面有具体介绍)。2.Cors 3.使用代理 4.websocket跨域

1.JSONP

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data,那么a.html中的代码就可以这样:

<script>
function doSomething(jsonData)
    

</script>
<script src="http://example.com/data?callback=doSomething"></script>

因为是当做一个js文件来引入的,所以http://example.com/data返回的必须是一个能执行的js文件

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

基于JSONP的实现原理,所以JSONP只能是“GET”请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了(所以如今它也基本被淘汰了)

2.Cros(跨域资源共享)解决跨域问题

Cross-origin resource sharingCORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

只要同时满足以下两大条件,就属于简单请求。

(1) 请求方法是以下三种方法之一:
     HEAD
     GET
     POST
(2)HTTP的头信息不超出以下几种字段:
     Accept
     Accept-Language
     Content-Language
     Last-Event-ID
     Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。

1.对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

2.非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight).也就是说在正式的请求后台之前,浏览器会先发一个预请求options表示这个请求是用来询问的。

头信息里面,关键字段是Origin,表示请求来自哪个源。

除了Origin字段,"预检"请求的头信息包括两个特殊字段。

(1)Access-Control-Request-Method

该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

(2)Access-Control-Request-Headers

该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

这是一段http对应的响应

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

上面的HTTP回应中,关键的是Access-Control-Allow-Origin字段,表示http://api.bob.com可以请求数据。该字段也可以设为星号,表示同意任意跨源请求。

服务器回应的其他CORS相关字段如下。

Access-Control-Allow-Methods: GET, POST, PUT
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。


Access-Control-Allow-Headers: X-Custom-Header
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

Access-Control-Allow-Credentials: true
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。如果服务器不要浏览器发送Cookie,删除该字段即可。

Access-Control-Max-Age: 1728000
该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

摘自阮一峰博客 http://www.ruanyifeng.com/blog/2016/04/cors.html

3.使用代理

3.1nginx反向代理接口跨域

实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

nginx具体配置:

#proxy服务器
server 
    listen       81;
    server_name  www.domain1.com;

    location / 
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    

1.) 前端代码示例:

var xhr = new XMLHttpRequest();

// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;

// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();

2.) Nodejs后台示例:

var http = require('http');
var server = http.createServer();
var qs = require('querystring');

server.on('request', function(req, res) 
    var params = qs.parse(req.url.substring(2));

    // 向前台写cookie
    res.writeHead(200, 
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取
    );

    res.write(JSON.stringify(params));
    res.end();
);

server.listen('8080');
console.log('Server is running at port 8080...');

3.2Nodejs中间件代理跨域

node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。

3.2.1非vue框架的跨域(2次跨域)

利用node + express + http-proxy-middleware搭建一个proxy服务器。

1.)前端代码示例:

var xhr = new XMLHttpRequest();

// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;

// 访问http-proxy-middleware代理服务器
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

2.)中间件服务器:

var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();

app.use('/', proxy(
    // 代理跨域目标接口
    target: 'http://www.domain2.com:8080',
    changeOrigin: true,

    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) 
        res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
        res.header('Access-Control-Allow-Credentials', 'true');
    ,

    // 修改响应信息中的cookie域名
    cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
));

app.listen(3000);
console.log('Proxy server is listen at port 3000...');

3.)Nodejs后台同(nginx)

3.2.2vue框架的跨域(1次跨域)

利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers跨域信息了。

webpack.config.js部分配置:

module.exports = 
    entry: ,
    module: ,
    ...
    devServer: 
        historyApiFallback: true,
        proxy: [
            context: '/login',
            target: 'http://www.domain2.com:8080',  // 代理跨域目标接口
            changeOrigin: true,
            secure: false,  // 当代理某些https服务报错时用
            cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
        ],
        noInfo: true
    

4.WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

1.)前端代码:

<div>user input:<input type="text"></div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');

// 连接成功处理
socket.on('connect', function() 
    // 监听服务端消息
    socket.on('message', function(msg) 
        console.log('data from server: ---> ' + msg); 
    );

    // 监听服务端关闭
    socket.on('disconnect', function()  
        console.log('Server socket has closed.'); 
    );
);

document.getElementsByTagName('input')[0].onblur = function() 
    socket.send(this.value);
;
</script>

2.)Nodejs socket后台:

var http = require('http');
var socket = require('socket.io');

// 启http服务
var server = http.createServer(function(req, res) 
    res.writeHead(200, 
        'Content-type': 'text/html'
    );
    res.end();
);

server.listen('8080');
console.log('Server is running at port 8080...');

// 监听socket连接
socket.listen(server).on('connection', function(client) 
    // 接收信息
    client.on('message', function(msg) 
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    );

    // 断开处理
    client.on('disconnect', function() 
        console.log('Client socket has closed.'); 
    );
);

跨域讲解 https://segmentfault.com/a/1190000011145364

解决跨域的方式(9种)(代码片段)

 1.jsonp1)JSONP原理利用<script>标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的JSON数据。JSONP请求一定需要对方的服务器做支持才可以。2)JSONP和AJAX对比JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务... 查看详情

为什么会有跨域的问题出现,如何解决跨域问题.(代码片段)

  目录  什么是跨域  什么是同源策略解决方式1、jsonp1.1)去创建一个script标签1.2)script的src属性设置接口地址1.3)接口参数,必须要带一个自定义函数名要不然后台无法返回数据。1.4)通过定义函数名去接收后... 查看详情

springboot解决跨域的四种姿势(代码片段)

简介跨域我就不多说了,我们今天开门见山直接解决跨域的几种姿势,那就上姿势姿势姿势一importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.s 查看详情

解决cors跨域的filter(代码片段)

importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.core.Ordered;importjavax.servlet.*;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;/***desc:**@aut 查看详情

如何解决跨域问题(代码片段)

(1)考察目标1)跨域出现的原因2)解决的跨域的方式有哪些。(2)题目分析1)跨域出现的原因:同源策略。什么是同源策略:同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策... 查看详情

springboot的cros跨域问题经常始终不能解决跨域的原因(代码片段)

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因问题问题的根本原因配置方法SpringBoot2.2.X版本SpringBoot2.5.X版本问题在配置跨域的@Configuration的时候,发现无论是.allowedOrigns()还是.allowedOriginParrtens()都解决不了的时候请看... 查看详情

jquery中ajax处理跨域的三大方式(代码片段)

这篇文章主要介绍了jquery中ajax处理跨域的三大方式,感兴趣的小伙伴们可以参考一下由于JS同源策略的影响,因此js只能访问同域名下的文档。因此要实现跨域,一般有以下几个方法:一、处理跨域的方式:1.... 查看详情

antdesignprowebapi访问提示跨域的2种解决办法(代码片段)

一、通过配置文件配置proxy.ts设置代理在生产环境代理是无法生效的/***在生产环境代理是无法生效的,所以这里没有生产环境的配置*Theagentcannottakeeffectintheproductionenvironment*sothereisnoconfigurationoftheproductionenvironment*Fordetails,pleases... 查看详情

前端跨域的解决方式

前端与服务端数据交互时,涉及到跨域的一些问题。JavaScript出于安全的考虑,禁止了跨域调用其他页面的对象,也即同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。什么是跨域?如... 查看详情

为什么会有跨域的问题出现,如何解决跨域问题(代码片段)

为什么会有跨域的问题出现,如何解决跨域问题什么是跨域​定义:跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都... 查看详情

解决跨域问题(代码片段)

...同,它们就是不同源的,浏览器会限制他们之间的资源交互;跨域: 跨域的安全限制只针对浏览器,服务器是没有跨域的安全限制的; 解决跨域的两种方法://1.jquery里利用<scriptsrc=‘‘>来解决跨域问题//1.引如jquery文件<scrip... 查看详情

vue基础系列(二十五)——axios解决ajax请求跨域的问题——方式二(代码片段)

...址,那么这个如果以/message为标头的请求路径,标志着跨域请求,然而请求路径也会把标头给加进去,但是我们又不需要,所以,给请求路径通过一个正则表达式恢复原样:pathRewrite:'^/message':''//... 查看详情

springboot的cros跨域问题经常始终不能解决跨域的原因(代码片段)

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因问题问题的根本原因配置方法SpringBoot2.2.X版本SpringBoot2.5.X版本问题在配置跨域的@Configuration的时候,发现无论是.allowedOrigns()还是.allowedOriginParrtens()都解决不了的时候请看... 查看详情

springboot的cros跨域问题经常始终不能解决跨域的原因(代码片段)

SpringBoot的Cros跨域问题经常始终不能解决跨域的原因问题问题的根本原因配置方法SpringBoot2.2.X版本SpringBoot2.5.X版本问题在配置跨域的@Configuration的时候,发现无论是.allowedOrigns()还是.allowedOriginParrtens()都解决不了的时候请看... 查看详情

跨域的三种解决方式

跨域问题跨域问题对于WEB前端工程师来说是比较重要的一个问题,因为我们时常需要去解决这样的问题,在其他类型的前端开发来说,他们并没有跨域问题跨域问题的产生因为浏览器有同源策略:只有在同域名,同端口,同协议... 查看详情

springboot解决全局和局部跨域问题的两种方式(代码片段)

前言在如今前后端分离的开发模式下,跨域是一个非常经典的问题,解决的方式也有很多,比如代理服务器,使用JSONP我之前也写过一篇解决跨域问题的文章,感兴趣的可以参考:解决Vue前后端跨域问题的... 查看详情

vue项目中常用解决跨域的方法(代码片段)

一、什么是跨域?跨域问题的出现是因为浏览器的同源策略问题。所谓同源就是必须有以下三个相同点:协议相同、主机相同、端口相同。如果其中有一项不同,即出现非同源请求,就会产生跨域。当我们请求一... 查看详情

详解cors跨域的几种不同实现方式(代码片段)

CORS定义CORS是一个W3C标准,全称是"跨域资源共享"(Cross-originresourcesharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。提供了Web服务从不同域传来沙盒脚本的方法,以避开浏览器的... 查看详情