初识"跨域请求"和"同源策略"

举报
辰兮 发表于 2022/03/22 23:57:38 2022/03/22
【摘要】 本章节小编初识跨域请求和同源策略,分享获取新知,大家一起进步 文章目录 一、同源策略二、跨域讲解三、跨域请求解决方案 一、同源策略 什么是同源策略 所谓同源...

本章节小编初识跨域请求和同源策略,分享获取新知,大家一起进步



一、同源策略

什么是同源策略

所谓同源是指,域名,协议,端口相同。
所谓“同源策略“,简单的说就是基于安全考虑,当前域不能访问其他域的东西。


拓展 什么是协议,域名,端口?

解释:假如一个网址是 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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。