• 首页

  • 归档

  • 标签

  • 分类

  • 友链
M S B l o g
M S B l o g

ms

获取中...

06
05
总结
问题
教程
javascript
vue

什么是跨域以及如何解决

发表于 2021-06-05 • 总结 问题 前端 javascript vue vue.js 服务器 • 被 1,470 人看爆

为什么会产生跨域呢,因为浏览器为了安全采用了一系列的安全机制,其中有一个是同源策略。何为同源策略(same-origin policy)。简单来讲同源策略就是浏览器为了保证用户信息的安全,防止恶意的网站窃取数据,禁止不同域之间的JS进行交互。对于浏览器而言只要域名、协议、端口其中一个不同就会引发同源策略

同源策略:

同源策略是浏览器的一个安全限制,从一个源加载的文档或者脚本默认不能访问另一个源的资源
是指协议,域名,端囗都要相同,其中有一个不同都会产生跨域

image.png

跨域流程:

这个跨域请求的实现是通过预检请求实现的,先发送一个OPSTIONS探路,收到响应允许跨域后再发送真实请求
跨域是要请求的、新的端口那个服务器限制的,不是浏览器限制的。

跨域请求流程:
非简单请求,浏览器自动发出一个"预检"请求


       -----1、预检请求、OPTIONS ------>
       <----2、服务器响应允许跨域 ------
浏览器 |                               |  服务器
       -----3、正式发送真实请求 -------->
       <----4、响应数据   --------------

预检请求

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错

非简单请求和简单请求

只要同时满足以下两大条件,就属于简单请求。

1) 请求方法是以下三种方法之一:

HEAD
GET
POST

2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同时满足上面两个条件,就属于非简单请求。

解决跨域

方法一:使用nginx反向代理

设置nginx包含admin和gateway。每次请求都先请求nginx,这样端口就统一了
image.png

方法二:在服务器配置配置允许跨域

让服务器告诉预检请求能跨域

在响应头中添加:

  • Access-Control-Allow-Origin : 支持哪些来源的请求跨域
  • Access-Control-Allow-Method : 支持那些方法跨域
  • Access-Control-Allow-Credentials :跨域请求默认不包含cookie,设置为true可以包含cookie
  • Access-Control-Expose-Headers : 跨域请求暴露的字段
    CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
  • Access-Control-Max-Age :表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将失效

springboot项目中可以添加过滤器,允许跨域

@Configuration // gateway
public class GulimallCorsConfiguration {

    @Bean // 添加过滤器
    public CorsWebFilter corsWebFilter(){
        // 基于url跨域,选择reactive包下的
        UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
        // 跨域配置信息
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许跨域的头
        corsConfiguration.addAllowedHeader("*");
        // 允许跨域的请求方式
        corsConfiguration.addAllowedMethod("*");
        // 允许跨域的请求来源
        corsConfiguration.addAllowedOrigin("*");
        // 是否允许携带cookie跨域
        corsConfiguration.setAllowCredentials(true);
        
       // 任意url都要进行跨域配置
        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }
}

其他方法

  • (1)设置document.domain解决无法读取非同源网页的 Cookie问题
    因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)
// 两个页面都设置
document.domain = 'test.com';
  • (2)跨文档通信 API:window.postMessage()
    调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)

它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

// 监听 message 消息
window.addEventListener('message', function (e) {
  console.log(e.source); // e.source 发送消息的窗口
  console.log(e.origin); // e.origin 消息发向的网址
  console.log(e.data);   // e.data   发送的消息
},false);
  • (3)JSONP

JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。

核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

①原生实现:

<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
 
// 处理服务器返回回调函数的数据
<script type="text/javascript">
    function dosomething(res){
        // 处理获得的数据
        console.log(res.data)
    }
</script>

② jQuery ajax:

$.ajax({
    url: 'http://www.test.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",    // 自定义回调函数名
    data: {}
});

③ Vue.js

this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})
分享到:
如何善用搜索引擎(Google Hacking)
Certbot查看证书过期时间,手动续期以及自动续期
  • 文章目录
  • 站点概览
ms

MSms

⚓️HelloWorld⚓️

QQ Email RSS
看爆 Top5
  • MyBatis-Plus分页查询 5,937次看爆
  • @Autowired与@Resource的区别 4,755次看爆
  • feign远程调用及异步调用丢失请求头问题 4,527次看爆
  • spring cloud中OpenFeign整合Sentinel启动报错 4,425次看爆
  • Certbot查看证书过期时间,手动续期以及自动续期 3,303次看爆

Copyright © 2025 ms · 湘ICP备20015239号

Proudly published with Halo · Theme by fyang · 站点地图