深度解析Web开发中的跨域问题

什么是跨域

问题背景

  • 以下是跨域的标准定义:

跨域指的是在浏览器中,当一个网页(或者Web应用)尝试访问不同域名、不同端口或不同协议的资源时,浏览器会限制该行为,防止潜在的安全风险。跨域问题是由浏览器的同源策略(Same-Origin Policy)所引起的。

同源策略是一种安全策略,是浏览器的一项重要基础安全机制。它要求网页只能与同一域名、协议和端口的资源进行交互。同源策略的存在是为了防止恶意网站获取用户的敏感信息或进行中间人攻击等安全问题。

  • 很显然,跨域就是在浏览器请求资源的过程中发生的
  • 浏览器请求资源时,如果请求的目标和当前页面的域名、端口或协议不一致,就会触发跨域问题
  • 具体来说,以下情况被认为是跨域访问:
    1. 不同域名:例如,www.example.com 和 api.example.com。
    2. 不同端口:例如,www.example.comwww.example.com:8080。
    3. 不同协议:例如,http://example.comhttps://example.com。
  • 现在的Web开发中都是前后端分离的开发模式,数据的获取并非同源,所以跨域的问题在我们日常开发中特别常见
  • 一般而言,跨域问题是在以下情况下产生的:

AJAX请求:当通过XMLHttpRequest对象发送异步请求时,如果请求的目标和当前页面的域名、端口或协议不一致,就会触发跨域问题。

资源加载:在网页中引入了来自不同域的外部资源,比如CSS、JavaScript、图片等文件时,如果资源服务器不允许跨域访问,也会产生跨域问题

广义的跨域

  • 其实浏览器加载的资源很多都是跨域的,只是有些资源的加载浏览器是允许的
  • 图片、CSS、Script等资源是不受同源策略限制的,一般不会触发跨域跨问题

狭义的跨域

  • 这里的跨域主要说的是 ajax 请求无法完成
  • 跨域问题主要是在浏览器环境下出现的,当浏览器发现请求跨域时,会在请求头中加上一个Origin字段,目标服务器会返回一个Access-Control-Allow-Origin的响应头,确定是否允许跨域访问

跨域解决方案

古老的JSONP

概念
  • JSONP(JSON with Padding)
原理
  • JSONP的优点就是因为他够老,能兼容各种浏览器,无兼容问题,众生平等
  • 他发送的不是ajax请求,而是利用了script标签加载机制。他发送的不是ajax请求
  • 了解了相关机制,我们看一下具体实现:
  • 客户端代码
function jsonp() {
    var script = document.createElement('script');
    script.type = 'text/javascript';
​
    // 传参并指定回调执行函数为backFn
    script.src = 'http://localhost:8100/getUserInfo?uid=100&callback=backFn';
    document.head.appendChild(script);
}
​
// 回调执行函数
function backFn(res) {
    alert(JSON.stringify(res));
}
​
document.getElementById('btn_get_data').addEventListener('click',()=>{
    jsonp();
});
  • 服务端代码
let uid = ctx.query.uid;
let callback=ctx.query.callback;
ctx.body = 'backFn({"code": 0, "user": "admin"})';

CORS跨域解决方案

概念
  • CORS(Cross-origin resource sharing)即“跨域资源共享“
  • 在出现CORS标准之前, 我们还只能通过jsonp(jsonp跨域请求详解)的形式去向“跨源”服务器去发送 XMLHttpRequest 请求,这种方式吃力不讨好,在请求方与接收方都需要做处理,而且请求的方式仅仅局限于GET。所以 ,CORS标准必然是大势所趋,并且市场上绝大多数浏览器都已经支持CORS。
原理
  • 支持CORS请求的浏览器一旦发现 ajax 请求跨域,会对请求做一些特殊处理,对于已经实现CORS接口的服务端,接受请求,并做出回应
  • 有一种情况比较特殊,如果我们发送的跨域请求为“非简单请求”,浏览器会在发出此请求之前首先发送一个请求类型为OPTIONS的“预检请求”,验证请求源是否为服务端允许源,这些对于开发这来说是感觉不到的,由浏览器代理
  • 总而言之,客户端不需要对跨域请求做任何特殊处理
  • 有关CORS跨域解决方案的具体介绍,可以看这篇博客:
  • 我们在开发过程中,只需作这两个步骤,即可解决跨域问题:
前端
// 创建 Axios 实例
const myAxios = axios.create({
  baseURL: "http://localhost:8083/api", // 设置请求的基础URL(后端请求地址)
  withCredentials: true,
});
后端
  /**
     * 允许跨域请求
     *
     * @param registry registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOrigins("http://localhost:7070", "http://localhost:3000","http://120.55.62.195:7071")  // 前端请求地址
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                .maxAge(3600);
    }

总结

  • 总之,跨域问题在Web开发过程中很常见,只要搞清楚跨域产生的原因,解决跨域问题并不困难
  • 这里另外补充几种常见的跨域解决方法,稍作了解:

要解决跨域问题,可以采取以下常见方法: ​ JSONP(JSON with Padding):通过动态创建<script>标签,利用<script>标签没有跨域限制的特性,实现跨域请求。 CORS(Cross-Origin Resource Sharing):在服务器端设置响应头,允许指定的域名或所有域名进行跨域访问。 代理(Proxy):在自己的服务器上设置一个代理接口,将跨域请求转发到目标服务器上。 WebSocket:使用WebSocket协议进行双向通信,不受同源策略限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值