初识"跨域请求"和"同源策略"
本章节小编初识跨域请求和同源策略,分享获取新知,大家一起进步
一、同源策略
什么是同源策略
所谓同源是指,域名,协议,端口相同。
所谓“同源策略“,简单的说就是基于安全考虑,当前域不能访问其他域的东西。
拓展
什么是协议,域名,端口?
解释:假如一个网址是 http://baidu.com:8080?user=name&pwd=password
http://
是协议baidu.com
是域名(注意:前面加上“www”即www.baidu.com不是域名)8080
是端口- user=name&pwd=password 是地址带的参数
举例
如果你有一个服务器A,你所需要的script,css,php文件都在服务器A,你写的html也在服务器A上,然后运行,出现了效果,如果你想在另一台电脑上运行你的项目(注意另一台电脑无论有没有开启服务器,效果还是会显示出来的),只要把你写在服务器A上的协议,域名,端口以及你的项目名称复制下来,在另一台电脑上运行,同样会出现相同的效果,这就实现了同源。
简单来说,就是你的协议,域名,端口甚至项目名称都一样,不同电脑都能实现同样的效果。
二、跨域讲解
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
当前页面URL | 被请求的页面URL | 是否跨域 | 原因 |
---|---|---|---|
http:// www.test.com | http:// www.test.com/index.html | 否 | 同源(协议、域名、端口)相同 |
http:// www.test.com | https:// www.test.com/index.html | 是 | 协议不同(http/https) |
http:// www.test.com | http:// www.baidu.com | 是 | 跨域(主域名不同baidu/test) |
http:// www.test.com | http://blog.test.com | 是 | 子域名不同(www/blog) |
http:// www.test.com:8080 | http:// www.test.com:8081 | 是 | 端口号不同(8080/8081) |
举例
如果有两个服务器,服务器A和服务器B,服务器A上存储了php数据,script,甚至是css这些文件,而你在服务器B上只写了html,然后你所在的服务器B上动态创建script,css,php数据(使用ajax请求),向服务器A上请求你想要的script,css,php数请求据(使用ajax)这些文件,请求这些文件后,你再在服务器B上运行你的html,虽然你的地址是在服务器B上,但是你还是可以运行效果与在服务器A上运行的效果是一样的,这样就是跨域名,跨端口,跨协议,实现了跨域。
简单来说,就是你请求的文件,只要含有“src”,“href”这些属性,你就能在其他服务器上,请求你所需要的文件,然后在自己的服务器上运行,就实现了跨域(跨域名,跨端口,跨协议)。
三、跨域请求解决方案
关于跨域请求有很多解决方案,下面举两个常见的方案
①通过jsonp跨域
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信
小结:即是动态创建
(1)原生实现:
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.test.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
// 回调执行函数
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
服务端返回如下(返回时即执行全局函数):
handleCallback({"status": true, "user": "admin"})
- 1
(2)jquery ajax:
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
(3)vue.js:
this.$http.jsonp('http://www.test.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
- 1
- 2
- 3
- 4
- 5
- 6
(4)后端node.js代码示例:
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
var params = qs.parse(req.url.split('?')[1]);
var fn = params.callback;
// jsonp返回设置
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ')');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
jsonp缺点:只能实现get一种请求。
② 跨域资源共享(CORS)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。
前端设置:
- ①原生ajax
// 前端设置是否带cookie
xhr.withCredentials = true;
- 1
- 2
例子
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- ②jQuery ajax
$.ajax({
...
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
...
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- ③vue框架
axios设置:
axios.defaults.withCredentials = true
- 1
vue-resource设置:
Vue.http.options.credentials = true
- 1
服务端设置
若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。
- Java后台:
/*
* 导入包:import javax.servlet.http.HttpServletResponse;
* 接口参数中定义:HttpServletResponse response
*/
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain.com");
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true");
// 提示OPTIONS预检时,后端需要设置的两个常用自定义头
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
The best investment is in yourself
2020.04.26 记录辰兮的第58篇博客
文章来源: blessing.blog.csdn.net,作者:辰兮要努力,版权归原作者所有,如需转载,请联系作者。
原文链接:blessing.blog.csdn.net/article/details/105767657
- 点赞
- 收藏
- 关注作者
评论(0)