前端跨域问题总结

由于浏览器的同源策略(相同协议、域名、端口),导致跨域无法接口请求和DOM查询。

解决跨域方案:
一、JSONP

原理:利用含有src属性标签:<script>、<img>、<ifram>,这种获取外部资源没有跨域限制,通过url回调来实现跨域。
ajax与jsonp的区别:ajax是通过XMLHttpRequest获取非本页内容,而jsonp是动态添加script标签调用服务器提供的js脚本。
jsonp的缺点:只支持GET请求;无法保证跨域的安全;难以确定是否请求成功。
JSONP由两部分组成:回调函数和数据,回调函数是当响应到来时应该在页面调用的函数,在请求url中指定好的,数据就是传入回调函数中的JSON数据。格式如下:

url:http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler

响应数据:

flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});

代码实现

<!DOCTYPE html">
<head>
    <title></title>
    <script type="text/javascript">
	    // 得到航班信息查询结果后的回调函数
	    var flightHandler = function(data){
	        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
	    };
	    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
	    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
	    var script = document.createElement('script');   // 创建script标签,设置其属性
	    script.src = url;
	    document.body.appendChild(script);   // 把script标签加入body,此时调用开始
    </script>
</head>
<body>
 
</body>
</html>
二、CORS(跨域资源共享)

引用 :https://www.cnblogs.com/knowledgesea/p/6808411.html
原理:使用额外的HTTP头来告诉浏览器,让运行在一个域上的web应用被准许访问来自不同源服务器上指定的资源。需要前后端同时支持。浏览器会自动添加附加的头信息,服务端需要添加Access-Control-Allow-Origin为*或指定源地址。
实现过程:浏览器将CORS分为简单请求和非简单请求。
简单请求
(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

跨域简单请求时,浏览器自动添加Origin字段,说明请求哪个源(协议+域名+端口),服务器根据这个值,决定是否同意这次请求。响应头添加Access-Control-Allow-Origin字段,指定域名或 * 。

如果服务端需要发送Cookie,需要服务端指定Access-Control-Allow-Credentials字段为true,同时Access-Control-Allow-Origin字段必须指定域名,前端AJAX请求需要设置withCredentials为true。如下:

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

非简单请求:不满足以上条件的请求。
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求OPTIONS,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com  //指定域名
Access-Control-Request-Method: PUT  //请求方法
Access-Control-Request-Headers: X-Custom-Header  // 额外发送的头信息字段
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

预检请求回应:

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

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

三、Nginx反向代理

原理:Nginx 所代表的角色叫做负载均衡服务器或者反向代理服务器,所有请求首先到达 Nginx 上,再由 Nginx 根据提前配置好的转发规则,将客户端发来的请求转发到某一个 服务端 上去。在上线部署时配置。
正向代理:中间服务器代理客户端,
反向代理:中间服务器代理服务端。
在conf/nginx.conf中 http server 中添加如下配置:

location /api/ {
    proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8001;  #机器ip
    expires 0;
}
location ^~/SaaSPortal {
    alias /export/App/epp_saas_m_portal/SaaSPortal;
    try_files $uri $uri/ /SaaSPortal/index.html;
}
四、开发环境webpack配置proxy代理跨域请求

开发环境跨域:由于前后端分离开发,前端通过nodejs来运行,需要一个单独的接口,后端通过Tomcat来运行,也需要接口,从而导致跨域。开发完毕后生成静态文件夹拷贝到后端项目就不存在跨域问题。
vue.config.js 请求转发配置:

proxyTable: {
 '/api': {
   target:'http://api.douban.com/v2', // 你请求的第三方接口
   changeOrigin:true, 
	// 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,
	//这样服务端和服务端进行数据的交互就不会有跨域问题
   pathRewrite:{  // 路径重写,
    '^/api': ''  
	// 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX
	//这个地址的时候直接写成/api即可。
   }
  }
}
module.exports = {
    devServer: {
        host: 'localhost',
        port: 8080,
        proxy: proxyTable
    }
}

axios的baseURL配置:

import axios from 'axios'
Vue.prototype.$axios = axios
axios.defaults.baseURL = '/api'  //关键代码

使用例子:

axios.get("/movie/top250").then((res) => {
  res = res.data
  if (res.errno === ERR_OK) {
    this.themeList=res.data;
  }
 }).catch((error) => {
  console.warn(error)
})

原理

因为我们通过axios默认配置给url加上了前缀/api,我们访问/movie/top250就当于访问了:localhost:8080/api/movie/top250(其中localhost:8080是默认的IP和端口)。

在vue.config.js中的proxyTable中拦截了/api,并把/api及其前面的所有替换成了target中的内容,因此实际访问Url是http://api.douban.com/v2/movie/top250。

至此,纯前端配置代理解决axios跨域得到解决

五、websocket
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值