前后端分离项目,如何解决跨域问题?

跨域问题是前后端分离项目中非常常见的一个问题,举例来说,编程猫学习网站的前端服务跑在 8080 端口下,后端服务跑在 9002 端口下,那么前端在请求后端接口的时候就会出现跨域问题。

403 Forbidden 是HTTP协议中的一个状态码(Status Code),意味着后端服务虽然成功解析了请求,但前端却没有访问该资源的权限。

那怎么解决这个问题呢?通常有两个思路:

  • 前端使用 Nodejs 代理(开发环境下,生产环境下可以用 Nginx 替代)
  • 或者后端开启跨域资源共享

一、关于跨域

跨域对于前后端开发者来说,就像一块狗皮膏药,无论是面试还是开发中,都会经常遇到。

之所以出现跨域问题,是因为浏览器的同源策略,为了隔离潜在的恶意文件,为了防御来自歪门邪道的攻击,浏览器限制了从同一个源加载的文档或脚本与来自另一个源的资源进行交互。

前面我们提到了,前端跑在 8080 端口下,后端跑在 9002 端口下,这种情况就属于不同的源(域名不同,协议不同,端口不同),所以 8080 端口下的前端请求直接访问 9002 端口下的后端接口时就访问失败了。

那正确的打开方式是什么呢?我们前面也提到了,前端使用 Nodejs 代理或者后端开启跨域资源共享,我们一一来实践下。

二、Nodejs 代理

在 Nodejs 出现之前,JavaScript 编写的程序通常需要在用户的浏览器上执行,Node.js 出现后,JavaScript 也能用于服务端编程了。Nodejs 一系列的内置模块使得程序可以脱离 IIS、Apache 这种 Web 服务作为独立的服务器执行。

我们使用 Nodejs 来解决跨域问题的思路就是,在本地创建一个虚拟服务器,对 8080 端口下的前端请求进行代理,同时接收 9002 端口下的服务器端响应,这样服务端和服务端进行数据的交互就不会出现跨域问题了。

第一步,配置 Nodejs 代理服务

module.exports = {dev: {// PathsassetsSubDirectory: 'static',assetsPublicPath: '/',proxyTable: {'/api': {target: 'http://localhost:9002', // 你请求的第三方接口changeOrigin: false, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题pathRewrite: { // 路径重写,'^/api': '' // 替换target中的请求地址,也就是说以后你在请求http://api.codingmore.top/v2/XXXXX这个地址的时候直接写成/api即可。}},},
}
复制代码

第二步,配置前端访问请求路径

module.exports = merge(prodEnv, {NODE_ENV: '"development"',VUE_APP_BASE_API: '"/api"'// VUE_APP_BASE_API: '"http://localhost:9002"'
})
复制代码

第三步,重启前端服务

再次点击「登录」按钮,可以看到请求的 URL 发生了改变,原来是 http://localhost:9002/users/login,现在是 http://localhost:8080/api/users/login。与此同时,可以看到多了一个 Remote Address,端口也是 8080,也就是说经过 Nodejs 的代理,前后端的交互在同一个源下面了,这样就不会发生跨域问题了。

同时,可以看得到,服务器端返回的状态码变成了 200,表示请求成功。

三、开启跨域资源共享

跨域资源共享,也就是 Cross-Origin Resource Sharing,简拼为 CORS,是一种基于 HTTP 头信息的机制,通过允许服务器标识除了它自己以外的资源,从而实现跨域访问。

第一步,开启 CORS 支持

在 Spring Boot 应用中,加入 CORS 的支持简单到不忍直视,添加一个配置类就可以了。

@Configuration
public class GlobalCorsConfig {@Beanpublic CorsFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();// 设置你要允许的网站域名config.addAllowedOrigin("http://localhost:8080");//允许跨域发送cookieconfig.setAllowCredentials(true);//放行全部原始头信息config.addAllowedHeader("*");//允许所有请求方法跨域调用config.addAllowedMethod("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", config);return new CorsFilter(source);}
}
复制代码

第二步,重启后端服务,再次点击登录按钮,发现请求已经可以正常访问了。

本例中,后端返回 Access-Control-Allow-Origin: http://localhost:8080 就表示,跑在 9002 端口下的后端接口可以被 8080 端口的前端请求访问。

如果允许所有域名进行跨域调用的话,只需改变一行代码即可。

//允许所有域名进行跨域调用
config.addAllowedOriginPattern("*");
// 设置你要允许的网站域名
//        config.addAllowedOrigin("http://localhost:8080");
复制代码

对于 login 这种简单的请求来说,它们是不会触发 CORS 预检的,因此不需要在服务器端增加其他配置就可以了。那什么是简单请求呢?

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

那对于会触发 CORS 预检的非简单请求(比如说请求方法是 PUT 或 DELETE,或者 Content-Type 字段的类型是 application/json,或者请求消息头包含了一些自定义的字段),该怎么办呢?

非简单请求在正式通信之前,会增加一次 HTTP 查询请求,称为“预检”请求。预检请求通过后,才会返回正常的响应内容。

拿编程猫的文章管理页来举例,该页面会向后端发起一个 posts/queryPageable 的分页查询,该请求包含了一个自定义的消息头 Authorization,于是浏览器认为该请求是一个非简单请求,然后就会自动发起一次 OPTIONS 请求,但由于我们的 Spring Boot 项目整合了 SpringsScurity 安全管理框架,没有对OPTIONS请求放开登录认证,导致验证失败,文章分页请求的响应数据就没有返回回来。

第三步,通过以下代码给 OPTIONS 请求放行。

public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();//允许跨域请求的OPTIONS请求registry.antMatchers(HttpMethod.OPTIONS).permitAll();}
}
复制代码

再次重启后端服务,重新访问文章列表接口,发现有响应数据了。

非简单请求必须首先使用 OPTIONS 请求方法发起一个预检请求到服务器端,以获知服务器是否允许该实际请求。"预检请求“的使用,避免了跨域请求对服务器的用户数据造成未预期的影响。

我们来通过两张图片简单总结一下预检请求的整个过程,第一张,发起 OPTIONS 预检请求:

第二章,发起正式请求:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/735304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华容道问题求解_详细设计(五)之hash值和回放功能

&#xff08;续上文&#xff09; 布局的hash 值计算 笔者也参考了之前的一些文章&#xff0c;很多文章提到了怎么节省存贮空间来查找最优解&#xff0c;这不是笔者的目的。笔者的目的比较单一&#xff0c;就是找到最优解就行了。因此并没有在存贮上面进行过多的优化&#xff…

消息队列 MQ

文章目录 1. MQ 相关概念1.1 什么是 MQ1.2 为什么要用 MQ1.3 MQ 分类1.4 MQ 的选择 1. MQ 相关概念 1.1 什么是 MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO 先入先出&#xff0c;只不过队列中存放的内容是 message 而已&#x…

阿里云DSW做AI绘画时的显卡选择A10?V100?

V100是Volta架构&#xff0c;A10是Ampere架构&#xff0c;架构上讲A10先进点&#xff0c;其实只是制程区别&#xff0c;用起来没区别。 V100是HBM的内存读取&#xff0c;带宽大&#xff0c;但是DDR5的。 二块卡都是全精度为主的算力卡&#xff0c;半精度优势不明显。 需要用…

FPN(Feature Pyramid Network)

参考&#xff1a; 【目标检测】FPN(Feature Pyramid Network) - 知乎 Feature pyramid network是CVPR2017年的一篇文章&#xff0c;它在目标检测中融入了特征金字塔&#xff0c;提高了目标检测的准确率&#xff0c;尤其体现在小物体的检测上。 1. 动机(Motivation) 识别不同…

【读书笔记】针对ICS的ATTCK矩阵详解(一)

Techniques - ICS | MITRE ATT&CKhttps://attack.mitre.org/techniques/ics/ 一、初始访问&#xff08;Initial Access&#xff09; 该阶段&#xff1a;攻击者正在尝试进入ICS环境。 初始访问包括攻击者可能用作入口向量&#xff0c;从而可以在 ICS 环境中获得初始立足点的…

pytorch实现分割模型TransUNet

TransUNet是一个非常经典的图像分割模型。该模型出现在Transformer引入图像领域的早期&#xff0c;所以结构比较简单&#xff0c;但是实际上效果却比很多后续花哨的模型更好。所以有必要捋一遍pytorch实现TransUNet的整体流程。 首先&#xff0c;按照惯例&#xff0c;先看一下…

逼疯快递员的送货上门,谁来背锅?

快递上门的问题近几年来一直争论不休。 最近&#xff0c;随着新修订的《快递市场管理办法》正式实施&#xff0c;这个话题又成为了焦点。 消费者希望快递能够送上门省去麻烦&#xff0c;快递员希望统一送到代收点提高效率。 是消费者要求太高&#xff1f;快递员太过怠慢&…

[金三银四] 系统调用相关

2.36 系统调用的详细流程 Linux 在x86上的系统调用通过 int 0x80 实现&#xff0c;用系统调用号来区分入口函数。操作系统实现系统调用的基本过程是&#xff1a; 应用程序调用库函数&#xff08;API&#xff09;&#xff1b;API 将系统调用号存入寄存器&#xff08;EAX&#…

CKA备考攻略:掌握Pod日志收集,事半功倍的秘诀!

往期精彩文章 : 提升CKA考试胜算&#xff1a;一文带你全面了解RBAC权限控制&#xff01;揭秘高效运维&#xff1a;如何用kubectl top命令实时监控K8s资源使用情况&#xff1f;CKA认证必备&#xff1a;掌握k8s网络策略的关键要点提高CKA认证成功率&#xff0c;CKA真题中的节点维…

2.JavaWebMySql基础

导语&#xff1a; 一、数据库基本概念 1.什么是数据库 2.关于MySql数据库 二、MySQL的安装与卸载 安装步骤&#xff1a; 卸载步骤&#xff1a; 三、MySQL服务操作 1.服务启动和关闭&#xff1a; 2.登录和退出MySQL&#xff1a; 3.服务自启动&#xff1a; 4.命令行登…

Python实现线性查找算法

Python实现线性查找算法 以下是使用 Python 实现线性查找算法的示例代码&#xff1a; def linear_search(arr, target):"""线性查找算法:param arr: 要搜索的数组:param target: 目标值:return: 如果找到目标值&#xff0c;返回其索引&#xff1b;否则返回 -1…

【玩转Linux】有关Linux权限

目录 一.Linux权限的概念 1. 权限的本质 2.Linux中的用户 3.Linux中的权限管理 (1)文件访问者的分类 (2)文件类型和访问权限&#xff08;事物属性&#xff09; ①文件基本权限 ②文件权限值的表示方法 (3)文件访问权限的相关设置方法 ① 用 户 表 示 符 / - 权 …

Vue3 快速上手从0到1,两小时学会【附源码】

小伙伴们好&#xff0c;欢迎关注&#xff0c;一起学习&#xff0c;无限进步 以下内容为vue3的学习笔记 项目需要使用到的依赖 npm install axios npm install nanoid vue-router npm install pinia npm install mitt 源码&#xff1a;Gitee 运行 npm install npm run dev需要运…

MacBook2024苹果免费mac电脑清理垃圾软件CleanMyMac X

CleanMyMac X是一款专业的Mac清理软件&#xff0c;具备多种强大功能。首先&#xff0c;它能够智能清理Mac磁盘上的垃圾文件和多余语言安装包&#xff0c;从而快速释放电脑内存。其次&#xff0c;CleanMyMac X可以轻松管理和升级Mac上的应用&#xff0c;同时强力卸载恶意软件并修…

windows使用pyenv

1、前言 虽然anaconda比pyenv相比有更好的python安装体验&#xff0c;但是有一个比较严重的问题的就是&#xff0c;他的python版本跨度不够大&#xff0c;一些老一些的项目的python版本找不到&#xff0c;比如py12306要求的python版本是3.6&#xff0c;在anaconda却找不到这个版…

查看pip当前关联python版本及位置

好久没用python了&#xff0c;把各种pip指向的环境忘光光啦&#xff0c;这里记录一下查看pip当前关联的python版本及位置的方法&#xff1a; pip -V结果&#xff1a; 我一般不用这个版本的python&#xff0c;去环境变量看了一下&#xff0c;原来是anaconda的Scripts自带pip&a…

gprof安装使用(CMake)说明

一、安装 1、gprof默认已安装&#xff0c;可安装相关图形处理 sudo apt-get install python graphviz sudo pip install gprof2dot 注意&#xff1a;在Debian中没有安装成功&#xff0c;报Python的版本不匹配 二、使用说明 1、使用CMake管理的工程&#xff1a; 重新配置CMa…

Elastic Stack--05--聚合、映射mapping

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.聚合(aggregations)基本概念桶&#xff08;bucket&#xff09;度量&#xff08;metrics&#xff09; 案例 11. 接下来按price字段进行分组&#xff1a;2. 若想对所…

LVS集群 ----------------(直接路由 )DR模式部署 (二)

一、LVS集群的三种工作模式 lvs-nat&#xff1a;修改请求报文的目标IP,多目标IP的DNAT lvs-dr&#xff1a;操纵封装新的MAC地址&#xff08;直接路由&#xff09; lvs-tun&#xff1a;隧道模式 lvs-dr 是 LVS集群的 默认工作模式 NAT通过网络地址转换实现的虚拟服务器&…

2024年【电工(初级)】考试内容及电工(初级)考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 电工&#xff08;初级&#xff09;考试内容根据新电工&#xff08;初级&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将电工&#xff08;初级&#xff09;模拟考试试题进行汇编&#xff0c;组成一套电…