跨域
域与跨域
域:指的是域名
域名对应的是一个ip地址
域名与ip地址的关系存储在域名解析系统中(DNS)
跨域
例如:有一个服务器A,有一个服务器B,当浏览器从服务器A上面请求资源并渲染完毕之后,再操作该页面的时候发送了另一个请求到服务器B,这个行为就称为跨域请求资源
跨域鉴定
当前域是http://localost:3000,当请求回来的页面中,又向其它服务器上请求资源:
不跨域
url: 'http://localost:3000/regist?username=name',
跨域
url: 'http://localost:3001/regist?username=name',
比较协议、域名、端口号三者有任何不同的地方,就可以判定为跨域
同源策略
浏览器有一个同源策略:不允许跨域请求资源(动态资源)
但是静态资源是不受同源策略的影响
总结:同域下,静态资源与动态资源都可以直接获取(同源策略)
跨域下,静态资源可以直接获取,动态资源不能直接获取(同源策略)
JSONP
jsonp:json + padding
jsonp就是一种跨域请求资源的方式,json是一种数据格式
我们可以利用script表现出来的无视同源策略的特点,将该标签上的src指向目标服务器上的接口
向目标服务器发送方法名称以及数据
服务器接收数据,并返回数据(要在方法中)
客户端预定义好该方法,让方法去执行,即可解决跨域
注意:需要跨域的服务器配合(将数据方法方法中执行)
假设有两个服务器A port=3000,B port=3001
B服务器配置
// 引入模块
let http = require('http');
let url = require('url');
// 创建服务器
http.createServer((req, res) => {
// 解析地址
let obj = url.parse(req.url, true);
// 定义msg接口
if (obj.pathname === '/msg') {
res.end('console.log("success")');
}
}).listen(3001)
当在浏览器中输入localhost:3001/msg,可以打印出console.log(“success”)
想要在A服务器下请求到B服务器下的数据,可以用script标签
<script>
// 由于静态资源不会跨域,所以可以通过script标签,向B服务器发送请求
let script = document.createElement('script');
document.body.appendChild(script);
// 通过script的src属性,向B服务器发送请求
script.src = 'http://localhost:3001/msg;
// 监听标签加载完毕
script.onload = function() {
console.log('标签加载完毕');
}
</script>
此时在浏览器中输入 localhost:3000/web 可以顺利打印出success
- 使用B服务器下的数据
B服务器配置
// 引入模块
let http = require('http');
let fs = require('fs');
let path = require('path');
let url = require('url');
let qs = require('querystring');
let data = {
title: 'test',
color: 'red'
}
// 创建服务器
http.createServer((req, res) => {
// 解析地址
let obj = url.parse(req.url, true);
// 定义msg接口
if (obj.pathname === '/msg') {
// 返回一个函数的形似fn(data)
res.end(`${obj.query.fn}(${JSON.stringify(data)})`);
}
}).listen(3001)
A页面配置
<div id="result"></div>
<script src="web/js/ickt.js"></script>
<script>
// 定义一个接收数据的方法
function func(data) {
document.getElementById('result').innerHTML = `<h1 style="color: ${data.color}"> ${data.title} </h1>`;
}
// 由于静态资源不会跨域,所以可以通过script标签,向B服务器发送请求
let script = document.createElement('script');
document.body.appendChild(script);
// 通过script的src属性,向B服务器发送请求
script.src = 'http://localhost:3001/msg?color=red&num=100&fn=func';
// 监听标签加载完毕
script.onload = function() {
console.log('标签加载完毕');
}
</script>
这样就可以在A页面中渲染出B服务器的数据
jQuery中的JSONP
使用方式:
$.ajax({
url: 请求的路径
type: 请求的方式
dataType: 'jsonp'
jsonpCallback: 指定回调函数的名称
success: 成功时候执行的回调函数
})
注意:请求成功会执行success方法,即使指定了jsonpcallback方法,success仍然会执行
<script>
// 定义一个接收数据的方法
function func(data) {
console.log(data);
document.getElementById('result').innerHTML = `<h1 style="color: ${data.color}"> ${data.title} </h1>`;
}
// jQuery简化了jsonp请求
$.ajax({
url: 'http://localhost:3001/msg',
// 表示jsonp请求
dataType: 'jsonp',
// 指定回调函数名称
jsonpCallback: 'func',
success(res) {
console.log(res);
}
})
</script>
代理模板跨域
在html中,通过iframe定义框架,可以引入其它的页面(有跨域问题,不能访问其它域的上一层框架)
在A域中,通过iframe引入B域的页面
在B域中,将请求重定向到A域的页面(代理模板)中
在A域中,通过代理模板解析数据,并执行A域的方法,实现跨域请求数据的获取
注意:需要B域服务器端的配合:重定向配合
HTML5跨域
服务器允许跨域要设置请求头
res.setHeader('Access-Control-Allow-Origin', '*'); //*表示所有的域都能访问
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', 'true');