title: 跨域 date: 2019-02-14 08:45:33 tags: [跨域]
跨域
什么是跨域为什么要跨域 ?
浏览器对于JavaScript的同源策略
的限制,例如a.cn不能调用b.js的数据。也是属于对网站的一种保护机制
同源策略:
是指
- 相同域名
- 相同端口
- 相同协议
跨域的三种方式
cls 服务端跨域 一
我们先模拟出不符合同源策略的生产环境
服务端代码
在这里是在这里是通过gulp起了一个8080
的端口
const gulp = require('gulp')
const webserver = require('gulp-webserver')
gulp.task("server", () => {
gulp.src('./')
.pipe(webserver({
host: "localhost",
port: 8080,
middleware(req, res) {
const data = { name: "neinei", age: 19 }
res.writeHead(200, {
'Content-Type': 'application/json;charset=utf-8',
})
res.end(JSON.stringify(data))
}
}))
})
复制代码
客户端js代码通过gulp起了一个人端口8000
的端口 然后把html
页面返回到浏览器
let fs = require("fs")
const gulp = require("gulp")
const webserver = require("gulp-webserver")
let result = fs.readFileSync("./index.html", "utf-8")
gulp.task("api", () => {
gulp.src('./')
.pipe(webserver({
host: "localhost",
port: 8000,
middleware(req, res) {
res.end(result)
}
}))
})
复制代码
客户端html展示页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
this is page
<script>
function request(url) {
return new Promise((resolve, reject) => {
let xml = new XMLHttpRequest()
xml.open("GET", url, false)
xml.onreadystatechange = function () {
if(xml.readyState!=4)return false
if(xml.status===200){
resolve(xml.responseText)
}
}
xml.send()
})
}
request('http://localhost:8080').then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
</script>
</body>
</html>
复制代码
在这里起了两个服务一个端口为8080一个端口为8000满足了跨域的需求 发起ajax试一下
添加语法'Access-Control-Allow-Origin': '*'
服务端代码
const gulp = require('gulp')
const webserver = require('gulp-webserver')
gulp.task("server", () => {
gulp.src('./')
.pipe(webserver({
host: "localhost",
port: 8080,
middleware(req, res) {
const data = { name: "neinei", age: 19 }
res.writeHead(200, {
'Content-Type': 'application/json;charset=utf-8',
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': '*'
})
res.end(JSON.stringify(data))
}
}))
})
复制代码
Access-Control-Allow-Origin
Access-Control-Allow-Origin 响应头指定了该响应的资源是否被允许与给定的origin共享
复制代码
*
对于不需具备凭证(credentials)的请求,服务器会以“*”作为通配符,从而允许所有域都具有访问资源的权限。
<origin>
指定一个可以访问资源的URI。
jsonp跨域 二
jsonp的原理
通过html
中带有src属性的标签发起请求
src
:因为src不受同源策略影响
一般使用<script>
标签
在请求路由中带去一个回调函数, 在服务端返回执行。
就可以在函数中的形参中拿到数据
服务端代码 端口号 8888
var http = require('http');
var url = require('url')
var data = JSON.stringify({ name: "heihei", age: 21 })
http.createServer(function (request, response) {
var parse = url.parse(request.url, true)
response.writeHead(200, { 'Content-Type': 'text/plain' });
if (parse.query.callback) {
response.end(parse.query.callback+"("+data+")")
return
}
response.end(data);
}).listen(8888, () => {
console.log(8888)
});
复制代码
客户端代码 端口8000
let fs = require("fs")
const gulp = require("gulp")
const webserver = require("gulp-webserver")
let result = fs.readFileSync("./index.html", "utf-8")
gulp.task("api", () => {
gulp.src('./')
.pipe(webserver({
host: "localhost",
port: 8000,
middleware(req, res) {
res.end(result)
}
}))
})
复制代码
客户端html
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
this is page
<script>
function cb(data) {
console.log(data)
}
var script = document.createElement('script')
script.setAttribute('src', "http://localhost:8888?callback=cb")
document.body.appendChild(script)
</script>
</body>
</html>
复制代码
客户端
-
动态创建一个
script
标签 -
创建一个函数来接受来接收数据 如上代码 我们创建了一个
cb
函数 -
设置
src
属性为我们的接口地址http://localhost:8888?callback=cb
-
通过
appendChild
方法吧script
插入body
插入后会自动发起请求
服务端
- 解析客户端传来的参数,通过
node
模块中的url
模块来解析
url.parse
:解析前端的请求参数 第二个参数为true
时会把参数解析成对象
parse.query
:会把参数解析放在parse.query的对象中
var parse = url.parse(request.url, true)
复制代码
- 判断是否传来
callback
函数然后通过end返回
if (parse.query.callback) {
response.end(parse.query.callback+"("+data+")")
return
}
复制代码
- 服务端的函数接收数据
function cb(data) {
console.log(data)
}
复制代码
降域 三
域名为http://b.com/b的网页以iframe的形式嵌在域名为http://a.com/a的网页中,它们来自不同的域名,正常情况下不能进行跨域访问。
但是当我们为两个页面都加上这样一句代码:
document.domain = 'wuxiaozhou.com';
这时候这两个页面就位于同一个域名下面了,就可以在页面a中对页面b进行操作了,两个页面可以互相访问。
项目地址: github.com/wangjinshen…