前端跨域小结

151 阅读2分钟

前提说明:在项目部署的时候,如果我们把web服务/数据服务,部署到同一台机器上,同一个端口下,则属于同源策略;反之,如果没有部署到相同的服务器,或者部署到相同的服务器下,但是端口号不是相同的,都属于非同源策略(跨域的官方名称)

一、跨域产生的原因:

  1. 当前页面的URL地址和请求数据接口的地址:如果协议、域名、端口号都是一致,则为同源策略,三者中只要有一个不一样,都是跨域请求

二、跨域解决方案:

  1. JSONP:利用了SCRIPT(IMG/IFRAME)等标签的src不存在跨域请求限制的特点,实现跨域请求

    • 只能是GET请求(不能是POST方式)
    • 传递给服务器的信息都是基于问号传参的方式传递过去的
    • 为了能够拿到服务器返回的结果,需要利用回调函数的机制,把客户端的某个函数名(全局)传递给服务器,有服务器接收到函数后做特殊处理 ?callback=func (callback这个名字是和服务器商定好的,一般都叫callback这个名字)
    // 前端代码:
    // 全局函数,赋值给回调函数
    function func(result) {
    	console.log(result);
    }
    
    	let script = document.createElement('script');
    	script.src = `http://127.0.0.1:1001/test?type=1&name=hdu&callback=func&_=${new Date().getTime()}`;
    // 加上时间戳是为了清除缓存(GET请求会有缓存)
    	document.body.appendChild(script);
    		// 请求结束,客户点拿到一个这样的结果:func({....}),浏览器会把函数执行(之所以这个函数在传递的时候需要是全局函数,因为后期获取到结果的时候,需要把它执行,只有全局函数才能在任何地方获取到)
    
    // 基于NODE实现的后端代码
        const express = require('express'),
    	app = express();
        app.listen(1001, () => {
        	console.log(`failure`);
        });
        
    /* 
     * JSONP的服务器端处理:所有的JSONP请求都需要服务  器端接收到请求后做特殊处理
     */
        app.get('/test', (req, res) => {
        let {
    	lx,
    	name,
    	callback //callback存储的就是客户端传递过来的函数名
        } = req.query;
        let data = {
    	code: 0,
    	codeText: 'SUCCESS',
    	text: `type:${type} === NAME:${name}`
        };
        //=>特殊处理:把客户端传递的函数名和需要给客户端的数据,拼成这样的格式 “函数(数据)”
        res.send(`${callback}(${JSON.stringify(data)})`);
     });
    
    
  2. CORS 跨域资源共享

    原理:让服务器允许客户端AJAX请求(基本上靠服务器设置允许跨域,客户端无需做太多的修改,直接正常发送AJAX请求即可)

    // node后端设置响应头头 
     app.use((req, res, next) => {
     	// 允许CORS跨域资源请求
     	// 1.允许的源ORIGIN有两种写法
     	//   "*" :允许所有客户端发送请求,但是不能携带资源凭证(Credentials===false)
     	//   "xxx":想要携带资源凭证,只能指定一个源,不能指定多个
     	res.header("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
     	res.header("Access-Control-Allow-Credentials", true);
     	res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization");
     	res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS,HEAD");
     });
    
  3. webpack

    ​ 原理:利用webpack-dev-server插件,构建本地服务server(预览本地开发的项目),我们发送AJAX请求,都先把请求发送给server,有server帮我们在发送给真正的服务器,server起了一个中间代理的作用,从而解决跨域的问题!

    但是上述操作是基于server这个服务的(webpack-dev-server),项目最后部署的时候,没有webpack-dev-server插件,此时我们需要基于其它方案(例如:nginx反向代理)实现出当初server服务代理的作用才可以!

  4. NGINX反向代理(还没有学习,后面补充)