前端碰到跨域问题,你一般是怎么解决的?...

今天来写一下老生常谈的话题------跨域!

去搜索引擎搜跨域的文章,简直是一抓一大把。但是,跨域问题确实无论是在面试中还是项目开发中,我们几乎无论做到哪个层面的码农,只要涉及到"请求"、"前后端交互"等等这些方面,都避不开跨域。既然躲不掉,那就直接面对,把跨域"咬碎嚼烂"。

什么是同源策略❓︎

同源策略:协议+域名+端口,是三个有任何一个不同就会造成跨域。

协议

  • 不同协议: 一个http 一个https, 同一域名不同协议,不允许通信❌(http默认端口是80、https默认端口是443)

域名:

  • 不同域名 : 一个 http://www.domain1.com、一个 http://www.domain2.com,不允许通信❌

  • 不同路径 : 一个 http://www.domain.com/a.js、一个 http://www.domain.com/js/b.js, 不允许通信❌

  • 域名和域名对应的ip : 一个http://www.domain.com、一个 http://192.168.0.1

  • 子域不同 : 一个http://a.domain.com、一个http://b.domain.com

端口:

  • 不同端口 : 一个 http://www.domain.com、一个 http://www.domain.com:8080, 不允许通信❌

同源策略能帮助我们隔离恶意文档,减少可能被攻击的媒介。


跨域解决方案

JSONP

JSONP(JSON with Padding) 利用<script>标签的跨域特性来实现跨域请求。

原理

  • 客户端(网页)通过动态创建一个<script>标签,并设置其src属性为目标服务器的URL,并在URL中包含一个回调函数的名称作为参数。
  • 服务器收到请求后,根据请求的参数解析出回调函数的名称,并将需要传递的数据包裹在该回调函数中。
  • 服务器返回的数据被包装在一个js函数调用中,比如: handleResponse({ name: 'John', age: 30 })
  • 浏览器加载<script>标签时,会向目标服务器发起请求,获取返回的js代码。
  • 由于返回的js代码是全局作用域下执行,因此回调函数会被调用,并将返回的数据作为参数传递给回调函数。
  • 客户端定义的回调函数被触发,可以在回调函数中处理返回的数据

缺点

  • 只能get请求

JSONP只适用GET请求,因为<script>标签的加载只能通过get方法实现。

另外,由于JSONP是通过将数据包裹在函数调用中返回的。因此,服务器需要提前知道客户端定义的回调函数的名称,双方进行约定。

  • 有风险

jsonp原理相对简单,但存在安全风险。如果服务器返回的脚本包含一些恶意代码,可能会对客户端产生安全威胁。所以说(1、要保证服务服务器是可信的,2、是要对返回的数据进行安全验证和处理)。


客户端

xml 复制代码
<script>
  // 定义回调函数来处理返回的数据
  function handleResponse(data) {
    console.log(data.name); // 输出:John
    console.log(data.age); // 输出:30
  }

  // 构造动态创建的<script>标签
  var script = document.createElement("script");
  script.src = "http://localhost:5000/jsonp?callback=handleResponse";
  document.body.appendChild(script);
</script>

请求过去的参数:

服务端(nestjs): 返回和前端约定好的函数,并且包裹了需要传递的数据进去,返回给前端。前端得到后再进行处理。即可实现跨域。

返回的是:

javascript 复制代码
// 定义回调函数来处理返回的数据
function handleResponse(data) {
    console.log(data.name); // 输出:John
    console.log(data.age); // 输出:30
}

控制台得到的结果:

以上这个例子就是jsonp处理跨域的一个例子。前端的地址是(http://127.0.0.1:5500/jsonp.html),后端的地址是(http://localhost:5000/jsonp)。根据此上(什么是同源策略)分析,不同端口是会跨域的,我们这里通过jsonp通过get接口处理了这么一个跨域的问题。


后端框架代码解决跨域

cors(cross-origin resource sharing(跨域资源共享))

:允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

说白了,cors 就是可以通过在服务端配置Access-Control-Allow-Origin: * 以及其他的一些参数。这么做的目的就是,由服务端告诉浏览器,只有满足这些条件你才能够请求我,否则就出现跨域限制,这就是做这个东西的目的,也就是安全.

thinkphp配置跨域:

在thinkphp框架中,使用Header类来设置跨域问题:

在控制器方法中添加以下代码:

less 复制代码
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept")

nestjs配置跨域:

在根目录的main.ts加上一句:

app.enableCors() // 启用跨域请求

上面这种既是任何域都能请求,实际开发中需要更详细地去控制:

php 复制代码
app.enableCors({
    origin: 'http://example.com',
    methods: 'GET,PUT,POST, DELETE',
    allowedHeaders: ['Content-Type', 'Authorization'],
    // ...
})

cors配置详细文档

...

其他的框架就具体搜索。

Nginx跨域配置

perl 复制代码
server {
    listen 80;
    server_name 'xxx';
    
    location / {
        add_header 'Access-Control-Allow-Origin' '*'; // * 全部;或者配置具体的域 http://xxx (最重要的就是这一句)
        add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    }
}

Apache跨域配置

php 复制代码
#
<VirtualHost *:80>
    ServerName localhost
    DocumnetRoot "路径"
    <Directory "路径">
        //...
        
        // 这里添加这一句
        Header set Access-Control-Allow-Origin * // * 全部,可以指定某个域
    </Directory>
</VirtualHost>

这里讲一下

总结

单纯前端除了jsonp,和在前端本地开发时proxy这种方案(这个proxy只在开发时用,上线还是要搞一下服务端的以上解决,要么Nginx什么配置、要么后端代码加cors)。也就是说,浏览器跨域限制的目的,就是为了不让你在前端解决这个问题,如果前端都能解决跨域了,什么人都可以去看某个服务端的代码,比如说哔哩哔哩的接口,如果他们那边不告侵权,我们随随便便可以用别人的接口,做一个不同的东西上线,用别人的资源来给自己造福,哪里来的安全性。全剧终!
☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。

相关推荐
夏幻灵1 小时前
HTML5里最常用的十大标签
前端·html·html5
Mr Xu_1 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝1 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions1 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发1 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_1 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞051 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、2 小时前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao2 小时前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly2 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强