文章目录
跨域产生的原因
第一种: 浏览器的限制
浏览器会对请求进行安全的信息校验。
第二种: 跨域
调用方于被调用方的协议, 域名, 端口,任何一个不一样,都会产生跨域问题。
第三种: XHR (XMLHttpRequest)
只要发出去的请求类型(type), 不是xhr就不会产生跨域
解决思路
-
从浏览器限制入手, 只要更改相关的参数, 不让浏览器做相关的限制, 就可以解决跨域的问题。
-
只要发出去的请求不是Type是XHR,就行。所以更改成,json即可,也就是JSONP,但是此方法不推荐,因为要在用户端进行很多相关的操作,才能解决。
注意点:使用JSONP,不仅仅是修改前端的代码,后端的代码也需要相关的修改
- 从支持的跨域的角度来解决。
方法1:设置被调用方允许跨域。但是很多时候,服务器不是我们自己的,无从修改。
方法2:调用方做修改。(也就是,隐藏跨域: 通过一个代理,在浏览器里发出去的都是同一个域名(A)的请求, 但是到代理服务器之后,将指定的URL转到需要跨域的域名(B)里)
此次主要讲解,第三个思路来解决跨域问题。
解决方法
服务器端(被调用方)适配跨域
实现原理: 图中红色虚线部分
运行以下的代码方法: node 简单服务器文件名.js
- 解决: 两端不在同一个域中
//这个只是一个, 简单服务器的实现代码
const http = require('http');
http.createServer( (request, response) => {
response.writeHead(200, {
'Access-Control-Allow-Origin': '*' // 意思为允许所有域来访问此接口 设置这个便可以解决
})
}).listen(8888);//服务器分配的端口号
console.log("开始运行服务端 PORT: 8888")
- 解决: 浏览器带Cookie访问服务器
注意: 带Cookie访问, 服务端不能设置 ‘Access-Control-Allow-Origin’ 为 ‘*’
//这个只是一个, 简单服务器的实现
const http = require('http');
http.createServer( (request, response) => {
if (request.headers['origin] != undefined ) { //如果为跨域请求, request中会有origin属性, 所以此种判断方法, 解决带Cookie跨域的情况
response.writeHead(200, {
'Access-Control-Allow-Origin': 'http://localhost:8887', // 意思为http://localhost:8887可以访问此接口
'Access-Control-Allow-Credentials': 'true' //允许携带, Cookie访问的设置
})
} else { //解决不带cookie的跨域
response.writeHead(200, {
'Access-Control-Allow-Origin': '*', // 意思为允许所有域来访问此
})
}
}).listen(8888);//服务器分配的端口号
console.log("开始运行服务端 PORT: 8888")
- 解决: 带自定义头, 如果服务端没有事先设置允许携带相header,会出现跨域问题
//这个只是一个, 简单服务器的实现
const http = require('http');
http.createServer( (request, response) => {
//先获取, 放出请求方中携带的自定义请求头的信息
let headers_keys = () => {
let headers_keys = '';
for (let key in request.headers) {
header_keys = header_keys + ',' + key;
}
return headers_keys;
}
//跨域响应头解决
if (request.headers['origin] != null) { //如果为跨域请求, request中会有origin属性, 所以此种判断方法, 解决带Cookie跨域的情况
response.writeHead(200, {
'Access-Control-Allow-Origin': 'http://localhost:8887', // 意思为http://localhost:8887可以访问此接口
'Access-Control-Allow-Credentials': 'true' //允许携带, Cookie访问的设置
'Access-Control-Allow-Headers': headers_keys //添加允许用户端自定义的头
})
} else { //解决不带cookie的跨域
response.writeHead(200, {
'Access-Control-Allow-Origin': '*', // 意思为允许所有域来访问此
})
}
}).listen(8888);//服务器分配的端口号
console.log("开始运行服务端 PORT: 8888")
用户端(调用方)隐藏跨域
原理: 图中黑色的虚线
过程: 用户端 --访问–> 本地代理服务器 --转发请求–> 真正需要请求的服务器
Nginx 方法 实现隐藏跨域
- 找到hosts文件
- 打开文件增加本地虚拟域名b.com
- 找到nginx下,以下图中的目录,创建文件 b.com.conf
- 在 b.com.conf 文件中,输入以下代码
server{
listen:80;
server_name b.com
location/{
proxy_pass http://localhost:8081/; //把所有对.b.com的请求转发到此url
}
location/cors_server{ //这里为, 中转路径, 将访问 /cors_server 的请求, 转发到 http://localhost:8080/test/
proxy_pas http://localhost:8080/test/; //这里为, 需要跨域访问的url
}
}
- 重启Nginx
总结
被调用方解决跨域问题, 需要修改被调用方的响应头中的内容, 达到跨域的目的, 但是这个方法有局限性, 当服务器不是自己的, 或者没有办法修改时, 比如腾讯, 百度的服务器, 你是无法修改的, 那么就要用调用方的解决方案的了, 也就是反向代理, 通过隐藏跨域, 浏览器看到的都是本域内的请求, 我们用户端的请求也的确时请求本域内的, 但是请求的不是, 最终需要请求的服务器, 而是访问本地代理的服务器, 通过代理服务器, 将我们的请求发出, 并返回相应的结果。