浏览器原理面试题 前端「前端面试进阶之浏览器原理」(13)


var server = http.createServer();
server.on('request', function(req, res) {
var params = querystring.parse(req.url.split('?')[1]);
var fn = params.callback;
// jsonp返回设置
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn'('JSON.stringify(params)')');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
JSONP的缺点:
具有局限性, 仅支持get方法
不安全,可能会遭受XSS攻击
(3)postMessage 跨域
postMessage是HTML5 XMLHttpRequest Level 2中的API , 且是为数不多可以跨域操作的window属性之一 , 它可用于解决以下方面的问题:
页面和其打开的新窗口的数据传递
多窗口之间消息传递
页面与嵌套的iframe消息传递
上面三个场景的跨域数据传递
用法:postMessage(data,origin)方法接受两个参数:
data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化 。
origin: 协议 主机 端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/" 。
1)a.html:(domain1.com/a.html)
2)b.html:(domain2.com/b.html)
(4)nginx代理跨域
nginx代理跨域 , 实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段 。
1)nginx配置解决iconfont跨域
浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外 , 此时可在nginx的静态资源服务器中加入以下配置 。
location / {
add_header Access-Control-Allow-Origin *;
}
2)nginx反向代理接口跨域
跨域问题:同源策略仅是针对浏览器的安全策略 。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题 。
实现思路:通过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;
}
}
(5)nodejs 中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名 , 实现当前域的cookie写入,方便接口登录认证 。
1)非vue框架的跨域
使用nodeexpresshttp-proxy-middleware搭建一个proxy服务器 。
前端代码:
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();
中间件服务器代码:
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/', proxy({
// 代理跨域目标接口