网络开发的隐形壁垒:如何巧妙解决跨域难题?

2024-02-03 19:52

本文主要是介绍网络开发的隐形壁垒:如何巧妙解决跨域难题?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是跨域

跨域是浏览器受同源(协议、域名、端口)策略的限制,不允许不同源的站点之间进行某些操作(如发送ajax请求,操作dom,读取cookie),如果不进行特殊配置是不能操作成功的,并且控制台会报如下跨域错误:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'xxxxxx' is therefore not allowed access

跨域出现的场景

两个常见的例子:

  • 前后端分离的项目联调时,客户端和服务端ip不一致

    一般前端本地服务启动在localhost:8080上,服务端接口部署在联调服务器上,此时向联调服务器发送请求的话就会发生跨域

  • 大型项目中可能需要多个服务,不同职责的服务部署在不同的端口上,甚至多个服务器上

    在当前网站页面上请求其他服务器或者其他端口上的接口,也会发生跨域,这种情况一般通过nginx反向代理解决

跨域解决方案

JSONP

原理:利用script标签的src属性不受同源策略的限制,并且资源加载完成后会被当作js脚本立即执行的特点,来达到跨域请求资源的目的。

需要做一些特殊处理:准备一个callback函数用于处理后端传来的数据,将callback函数的名字作为src属性中的query传给后端,后端收到后用callback函数名将数据包裹起来,使数据作为参数返回给前端,当资源加载完成,callback会立即被调用,此时的实参就是我们需要的数据。

var script = document.createElement('script');// 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);// 回调执行函数
function handleCallback(res) {alert(JSON.stringify(res));
}

服务端返回如下(返回时即执行全局函数):

handleCallback({"success": true, "user": "admin"})

JSONP的优缺点:

  • 优点

    • 兼容性好,支持老的浏览器
  • 缺点

    • 只支持get请求,因为script标签请求资源本质就是一个get请求
    • 需要服务端专门配置,把数据用callback函数名包裹起来再返回

CORS

CORS是w3c指定的跨域方案,支持所有类型的请求;兼容性:ie不能低于ie 10

CORS跨域方案将所有请求划分为简单请求和非简单请求两类,对其分别采用不同的处理方案。

简单请求

同时满足以下两个条件的请求属于简单请求:

  • 请求方法是getposthead中的一种
  • http头字段不超出:
  • Accept
  • Accept-Language
  • Accept-Language
  • Content-Type仅限于text/plainmultipart/form-dataapplication/x-www-form-urlencoded
简单请求流程

浏览器在请求头中自动加入origin字段,origin字段用来说明本次请求来自哪个源(协议+域名+端口),服务器根据这个值,决定是否同意这次请求。

如果origin指定的源,不在许可范围内,服务器会返回一个正常的http回应。浏览器发现,这个回应的头信息没有包含 Access-Control-Allow-Origin 字段,就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

如果Origin指定的域名在许可范围内,服务器返回的头字段中会包含Access-Control-Allow-Origin,它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

如何设置cookie?

  • cors请求默认不携带cookie,如果想要发送cookie,需要服务端和客户端同时设置
  • 一方面要服务器同意,指定Access-Control-Allow-Credentials: true
  • 另一方面,开发者必须在ajax请求中打开withCredentials属性。xhr.withCredentials = true;

非简单请求

预检请求

非简单请求需要先发出一个预检请求,预检请求方法是OPTIONS,用来获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响(PUT、delete)

请求头字段

  • Origin
  • Access-Control-Request-Method
  • Access-Control-Request-Headers

预检请求的回应

  • 如果允许跨源请求

    • Access-Control-Allow-Origin

    • Access-Control-Allow-Methods(返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。)

    • Access-Control-Allow-Headers(是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。)

    • Access-Control-Allow-Credentials

      • 如何设置cookie?

        • cors请求默认不发送cookie,如果想要发送cookie,需要服务端和客户端同时设置
        • 一方面要服务器同意,指定Access-Control-Allow-Credentials: true
        • 另一方面,开发者必须在AJAX请求中打开withCredentials属性。
    • Access-Control-Max-Age

      • 该字段可选,用来指定本次预检请求的有效期,单位为秒。在此期间,不用发出另一条预检请求。
  • 如果不允许,比如origin不在信任名单内

    • 会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。浏览器就会报错
正常请求

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

反向代理

跨域是浏览器的保护机制,如果绕过浏览器,使用代理服务器去请求目标服务器上的数据,就不会受跨域影响。因此前端可以通过脚手架或webpack配置devSever下的proxy选项,将/api开头的请求转发到真实服务器上。

在生产环境下也可以使用nginx配置反向代理来解决跨域。

学习资料:点此下载

这篇关于网络开发的隐形壁垒:如何巧妙解决跨域难题?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/675208

相关文章

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

SQL Server安装时候没有中文选项的解决方法

《SQLServer安装时候没有中文选项的解决方法》用户安装SQLServer时界面全英文,无中文选项,通过修改安装设置中的国家或地区为中文中国,重启安装程序后界面恢复中文,解决了问题,对SQLSe... 你是不是在安装SQL Server时候发现安装界面和别人不同,并且无论如何都没有中文选项?这个问题也

java内存泄漏排查过程及解决

《java内存泄漏排查过程及解决》公司某服务内存持续增长,疑似内存泄漏,未触发OOM,排查方法包括检查JVM配置、分析GC执行状态、导出堆内存快照并用IDEAProfiler工具定位大对象及代码... 目录内存泄漏内存问题排查1.查看JVM内存配置2.分析gc是否正常执行3.导出 dump 各种工具分析4.

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自