什么是跨域
- 浏览器同域策略要求协议、域名、 端口,都一样,只要一种不满足都属于跨域。
跨域有哪一些问题
1、无法获取非同源的cookie、localStorge,sensionStorge, indexedDB,
2、 iframe 页面无法获取
3、 无法发送ajax,fetch 请求,浏览器拒绝,需要服务端支持跨域设置CORS:
- 服务端设置响应头允许来源:
"Access-Control-Allow-Origin", "*"
- 服务端设置响应头允许cookie: 服务端 设置Access-Control-Allow-Credentials为true, XMLHttpRequest的withCredentials为true,跨域允许cookie发送
response.setHeader("Access-Control-Allow-Origin", "*");
- 服务端设置响应头允许methods:
response.setHeader("Access-Control-Allow-Methods", "*");
- 服务端设置允许响应头暴露:
response.setHeader("Access-Control-Expose-Headers", "*");
- 服务端设置请求的存储时间
response.setHeader("Access-Control-Max-Age", "3600");
js常见的跨域方式:(未完)
1、通过jsonp 跨域
- JSONP(JSON with Padding)是数据格式 JSON 的一种“使用模式”,可以让网页从别的网域要数据。
- 根据 XmlHttpRequest 对象受到同源策略的影响,而利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,而这种使用模式就是所谓的 JSONP。
- 用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析。
- 所有,通过Chrome查看所有JSONP发送的Get请求都是
js类型
,而非 XHR
缺点
- 只能使用Get请求
- 不能注册 success、error 等事件监听函数,不能很容易的确定 JSONP 请求是否失败
- JSONP 是从其他域中加载代码执行,容易受到xss跨站请求伪造的攻击.
步骤:
- 1.将传入的data数据转化为url字符串形式
- 2.处理url中的回调函数
- 3.创建一个script标签并插入到页面中
- 4.挂载回调函数
jsonp 代码实现
function encodeParam(url, obj) {
// 1.将传入的data数据转化为url字符串形式
// {id:1,name:'jack'} => id=1&name=jack
const dataString = url.indexof('?') ? '?' : '&';
for(let key in data) {
dataString += `${key}=${(data[key] !== undefinded ? data[key] : '' }`
}
return dataString;
}
const jsonp = function (url, data, callback) {
//promise 返回 new Promise((resolve, reject)=>{...callback(data)-->resolve(data)...})
let dataString = encodeParam(url, data);
// 处理url 中的回调函数
const cbfnName = `my_json_cb_${Math.ramdom().toString().repalce('.', '')}`;
dataString += `callback=${cbfnName}`;
// 3.创建一个script标签并插入到页面
const scriptEle = document.createElement('script');
scriptEle.src = `${url}${dataString}`
// 4、挂载回调函数
window[cbfnName] = function(data) {
callback(data);
// 处理完回调函数的数据之后,删除jsonp的script标
document.body.removeChild(scriptEle);
}
document.body.appendChild(scriptEle);
}
服务端代码
let express = require('express');
let app = express();
app.get('/student', function(req, res) {
let {...callback...} = res.query;
res.end(`${callback}(data)`)
})