浏览器的同源策略
-
源
window.origin或者location.origin可以得到当前源 如果两个url的 协议 域名 端口号 完全一致,那么这两个url就是同源 -
同源策略定义
浏览器规定 如果js运行在源A里,那么就只能获取源A的数据 不能获取源B的数据,即不允许跨域
实现跨域的两种方法
CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应
**Access-Control-Allow-Origin**响应头指定了该响应的资源是否被允许与给定的origin共享。
//server.js文件
//cors (前端和后端合作实现)
var http = require('http')// 引入 http 模块,用来创建 http 服务器
var fs = require('fs')// 引入 fs 模块,用来操作文件系统
var url = require('url')// 引入 url 模块,用来解析 url
var port = process.argv[2]// 拿到执行此脚本命令的第二个参数(即为 port),如 node server.js 8888,那么 port = 8888
if (!port) {
console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
process.exit(1)
}
var server = http.createServer(function (request, response) {
// 解析 url 拿到解析后的对象,形如 parsedUrl 图(见下文)
var parsedUrl = url.parse(request.url, true)
// 带 query 的 path,见下文 pathWithQuery
var pathWithQuery = request.url
var queryString = ''
// 判断是否带 query
if (pathWithQuery.indexOf('?') >= 0) {
// 带 query 的话则拿到它
queryString = pathWithQuery.substring(pathWithQuery.indexOf('?'))
}
var path = parsedUrl.pathname
var query = parsedUrl.query
// 拿到请求方法
var method = request.method
/******** 从这里开始看,上面不要看 ************/
console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)
// 处理 / 路由
if (path === '/index.html') {
// 设置响应状态码为 200
response.statusCode = 200
// 设置响应头 content-type 字段
response.setHeader('Content-Type', 'text/html;charset=utf-8')
let string = fs.readFileSync('./public/index.html').toString()
// 设置响应体内容
response.write(string)
// 结束并响应请求
response.end()
} else if (path === '/qq.js') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
response.write(fs.readFileSync('./public/qq.js'))
response.end()
} else if (path === '/qq.json') {
response.statusCode = 200
response.setHeader('Content-Type', 'text/json;charset=utf-8')
//cors设置允许访访的源
response.setHeader("Access-Control-Allow-Origin", "http://www.frank.com:9903")
let string = fs.readFileSync('./public/qq.json')
response.write(string)
response.end()
} else if (path === "/jsonp.js") {
response.statusCode = 200
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
const string = fs.readFileSync('./public/jsonp.js').toString()
const name = query.callBake
const data = fs.readFileSync('./public/qq.json').toString()
let string1 = string.replace("{ { data } }", data).replace("xxx", name)
response.write(string1)
response.end()
} else {
// 兜底,除了上面两种路由,其它路由都走此逻辑
response.statusCode = 404
response.setHeader('Content-Type', 'text/json;charset=utf-8')
response.write(`你输入的路径不存在对应的内容`)
response.end()
}
/******** 代码结束,下面不要看 ************/
})
// 监听 port 端口,只有执行了此语句才算启动了服务
server.listen(port)
// 命令行打印日志
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)
jspn跨域
node.js后端设置
json原理(前端和后端合作实现)
设置好函数
后台使用js文件调用函数,拿到数据
在引入js文件,解决跨域
缺点只能用GET请求,没有响应码
后端设置
//处理路由
if (path === "/jsonp.js") {
//设置响应状态码
response.statusCode = 200
//设置响应头Content-Type
response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
//读取json文件内容
const string = fs.readFileSync('./public/jsonp.js').toString()
//函数名
const name = query.callBake
//读取数据
const data = fs.readFileSync('./public/qq.json').toString()
//把数据写入json.js,并且设置函数名
let string1 = string.replace("{ { data } }", data).replace("xxx", name)
response.write(string1)
response.end()
}
前端代码
//jsonp实现跨域
const random = Math.random()
window[random] = (data) => {
console.log(data)
}
const script = document.createElement('script')
script.src = `http://www.qq.com:8888/jsonp.js?callBake=${random}`
script.onload = () => {
script.remove()
}
document.body.appendChild(script)
在vue-cli项目中使用反向代理
安装axios
npm install axios
在项目中引入axios
import axios from 'axios'
Vue.prototype.$axios = axios
使用axios发起get请求
this.get(url).then(response=>{
console.log(response)
}).catch(error=>{
console.log(err)
})
axios.get(url, {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
使用axios发起post请求
axios.post(url, {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
使用axios时需要使用反向代理解决跨域问题
在vue项目开发阶段,常常会碰到跨域请求的问题,我们能使用反向代理解决
解决方法:
\1. 在项目文件夹下创建 vue.config.js配置文件
// vue.config.js文件
module.exports = {
lintOnSave: false,
//添加如下代码
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080', //设置你调用的接口域名和端口号 别忘了加http
changeOrigin: true, //如果接口跨域,需要进行这个参数配置
secure: false, // 如果是https接口,需要配置这个参数
pathRewrite: {
'^/api': ''//这里理解成用‘/api’代替target里面的地址,后面组件中我们调用接口时直接用api代替
}
}
}
}
}
使用在main.js
// 引入axios
import axios from "axios"
// 给vue原型添加一个属性$axios 其属性值为axios
Vue.prototype.$axios = axios;
// 给axios设置一个默认请求地址 这样请求数据时/api可以省略不写 方便后期优化
axios.defaults.baseURL = "/api";
发起get请求
this.$axios.get('/api/')
.then(response => {
//成功返回
console.log(response)
console.log(response.data);
this.obj = response.data
})
.catch(error => {
//失败返回
console.log(error);
});