阅读 485

常用的-前端跨域的解决

跨域(非同源策略请求)

-同源策略请求 是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源  

ajax / fetch复制代码

跨域传输(跨域是指一个域下的文档或脚本试图去请求另一个域下的资源)

以下下三者一样就是同源,只要有一项不一样就是跨域

协议&域名&端口号

http://127.0.0.1:3000/index.html
http://127.0.0.1:4000/list.html//http:协议       127.0.0.1:域名       3000:端口号复制代码

一、 通过jsonp跨域

通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。

服务器拆分
  1. web服务器:静态资源 
  2. data服务器:业务逻辑和数据分析 
  3. 图片服务器


1.json.js

$.ajax({    url: 'http://127.0.0.1:8001/list',    method: 'get',    dataType: 'jsonp', //=>执行的是JSONP的请求    success: res => {        console.log(res);    }});复制代码

2.serverJSON.js

let express = require('express'),    app = express();app.listen(8001, _ => {    console.log('OK!');});app.get('/list', (req, res) => {    let {        callback = Function.prototype    } = req.query;    let data = {        code: 0,        message: 'JSONP哈哈哈'    };    res.send(`${callback}(${JSON.stringify(data)})`);});复制代码

Console控制台显示

{code:0,message:'JSONP哈哈哈'}复制代码

JSONP缺点:JSONP只能处理GET请求

二、 跨域资源共享(CORS)

- 客户端(发送ajax/fetch请求)

axios.defaults.baseURL = 'http://127.0.0.1:8888';axios.defaults.withCredentials = true;//👈重点axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';axios.defaults.transformRequest = function (data) {  if (!data) return data;  let result = ``;  for (let attr in data) {    if (!data.hasOwnProperty(attr)) break;    result += `&${attr}=${data[attr]}`;  }  return result.substring(1);};axios.interceptors.response.use(function onFulfilled(response) {  return response.data;}, function onRejected(reason) {  return Promise.reject(reason);});axios.defaults.validateStatus = function (status) {  return /^(2|3)\d{2}$/.test(status);}复制代码

- 服务器端设置相关的头信息(需要处理options试探性请求)

app.use((req, res, next) => {    res.header("Access-Control-Allow-Origin", "http://localhost:8000");  //=>*(就不能在允许携带cookie了) 具体地址
   //局限性  二者选其一  因为CORS的这个缺陷  出现了👇http proxy  =>webpack webpack-dev-server    res.header("Access-Control-Allow-Credentials", true);    res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length,Authorization, Accept,X-Requested-With");    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,HEAD,OPTIONS");    if (req.method === 'OPTIONS') {        res.send('OK!');        return;    }    next();});复制代码

三、  http proxy =>webpack webpack-dev-server

proxy相当于node给你模拟了一个ngnix服务请求,服务器请求服务器不存在跨域。proxy请求回来数据,从而解决跨域

-在webpack.config.js文件中:

devServer: {
        port: 3000,
        progress: true,
        contentBase: './build',
        proxy: {             
'/': {      //‘/’  在请求时不用设置前缀                
target: 'http://127.0.0.1:3001',                
changeOrigin: true //改变源 (当我们设置为true时 devserver会帮我们起一个服务,
                                 //来做中层的代理"与node中间件代理类似"])            }        }    }复制代码


四、ngnix反向代理(前端不需要做什么工作)

server {    listen       80;    server_name  www.baidu.com;    location / {        proxy_pass   www.baidu.cn; //反向代理        proxy_cookie_demo www.baidu.cn www.baidu.com;        add_header Access-Control-Allow-Origin www.baidu.cn;        add_header Access-Control-Allow-Credentials true;    }}复制代码


五、postMessage

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"

-server1.js

let express = require('express'),    app = express();app.listen(1001, _ => {    console.log('OK!');});app.use(express.static('./'));复制代码

-server2.js

let express = require('express'),    app = express();app.listen(1002, _ => {    console.log('OK!');});app.use(express.static('./'));复制代码

- A1.html

<body>    <iframe id="iframe" 
                     src="http://127.0.0.1:1002/MESSAGE/B.html"
                     frameborder="0"
                     style="display: none;">
    </iframe>      <script>        iframe.onload = function () {            iframe.contentWindow.postMessage('哈哈哈哈', 'http://127.0.0.1:1002/');        }        //=>监听B传递的信息        window.onmessage = function (ev) {            console.log(ev.data);        }    </script></body>复制代码

- B1.html

<body>    <script>        //=>监听A发送过来的信息        window.onmessage = function (ev) {            // console.log(ev.data);            //=>ev.source:A            ev.source.postMessage(ev.data + '@@@', '*');        }    </script></body>复制代码

六,七,八,九...................................................................睡醒了写


关注下面的标签,发现更多相似文章
评论