Ajax跨域如何解决?
1.什么是跨域
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
同源策略限制了以下行为:
Cookie、LocalStorage 和 IndexDB 无法读取
DOM 和 JS 对象无法获取
Ajax请求发送不出去
同源就是指,域名、协议、端口均为相同。
其中一个不一样就为跨域
2.跨域如何解决
1.jsonp方式
jsonp跨域是JavaScript设计模式中的一种代理模式。在html页面中通过相应的标签从不同域名下加载静态资源文件是被浏览器允许的(从js中调用不行)
我们可以动态的创建script标签,再去请求一个带参网址来实现跨域通信。局限是只能get请求。
客户端代码
//原生实现方式
//假如我们要通过input失去焦点事件请求数据
<body>
<input type="text">
<p></p>
<script>
let input=document.querySelectorAll('input')[0]
let p=document.querySelectorAll('p')[0]
// 声明函数
function fn(data){
input.style.border='1px solid red'
p.innerText=data.msg
}
//绑定事件
input.addEventListener('blur',function(){
// 获取用户输入的值
let username=this.value
//向服务器发送请求,查看用户名是否已经存在
//1.创建script标签
let script=document.createElement('script')
//2.设置标签的src属性进行请求
script.src='http://127.0.0.1:8000/script'
//3.插入父节点
document.body.appendChild(script)
})
</script>
</body>
node.js服务器代码
// 引入express
const { request, response } = require('express');
const express =require('express')
// 创建应用对象
const app =express();
// 创建路由规则
app.all('/script',(request,response)=>{//get后面的路径就是你浏览器访问的url路径
// 请求响应
let data={
code:1,
msg:'用户名已存在'
}
let str=JSON.stringify(data)
response.send(`fn(${str})`)
})
// 服务器监听
app.listen(8000,()=>{
console.log('服务器已经启动....')
})
jQuery的实现方式
//jquery实现方式
$.ajax({
url:'http://www.xxx.com/login',
type:'GET',
dataType:'jsonp',//请求方式为jsonp
jsonpCallback:'callback',
})
function callback(res) {
console.log(res);
}
特别注意的是,上面代码里 jsonpCallbacks属性传入的callback参数是服务器传回数据后需要调用的方法,上面代码中方法是callback();
2. 跨域资源共享CORS
这是目前主流的解决方案。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 因此,实现CORS通信的关键是服务器。
3.代理跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
#proxy服务器
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; #反向代理
proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
index index.html index.htm;
# 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
#add_header Access-Control-Allow-Origin http://www.domain1.com; #当前端只跨域不带cookie时,可为*
add_header Access-Control-Allow-Credentials true;
}
}
html代码
var xhr = new XMLHttpRequest();
// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;
// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();