浏览器同源策略导致跨域问题 No ‘Access-Control-Allow-Origin‘ header 原因及解决方式--(后端、nginx、前端)

news2025/1/22 17:42:41

目录

现象

原因

浏览器同源策略

导致结果:

解决方案

跨源资源共享(CORS)

各个端解决方法:

后端:

方式1:重载WebMvcConfigurer方法

方式2:配置监听CorsFilter

方式3:相关类上加注解 @CrossOrigin

注意事项:

Nginx解决:

情况1:

前端解决:


现象

本人身份:后端

今天部署线上环境前端代码时,发生了如下报错:

Access to XMLHttpRequest at 'http://192.168.1.11:8081/api/v1/sys/auth/login' from origin 'http://192.168.1.8:8101' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

经典的跨域问题,=探究一下这个现象的本质以及从3个端(后端、代理、前端)分别该怎么处理这个问题

 这个问题其实在开发环境是不会出现的,当把前端代码打包好后部署到线上环境,用Nginx跑起来后,发生了这个问题,发生这个问题的根本原因是由于浏览器的同源策略

原因

浏览器同源策略

同源策略(Same Origin Policy)是一种安全策略,它是浏览器最核心也是最基本的安全功能。同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。如果缺少了同源策略浏览器的安全使用会受到很大的影响。可以说web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源的三个条件:

域名、协议、端口都相同

假设 URL  A: http://192.168.1.8:8080/

下列URL与A是否同源比较

B


https://192.168.1.8:8080/

不同源,协议不同,一个是http,一个是https
Chttp://192.168.1.8:8081/不同源,端口号不同
Dhttp://192.168.1.9:8080/不同源,IP不同
Ehttp://192.168.1.8:8080/api 同源

导致结果:

  • 不能获取不同源的 cookie,LocalStorage 和 indexDB
  • 不能获取不同源的 DOM()
  • 不能发送不同源的 ajax 请求 (可以向不同源的服务器发起请求,但是返回的数据会被浏览器拦截)

上述的现象就是因为 ajax请求其实已经到了后端,后端也已经处理,但是因为浏览器的同源策略导致拒绝接收数据,所以其实这个现象在移动端不会出现,只会在浏览器出现

解决方案

其他方案如前端jsonp之类的方法,都有或大或小的弊端,看了比较久,介绍下面的方法

跨源资源共享(CORS)

Cross-Origin Resource Sharing 跨资源共享,作为W3C的标准,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。是跨域ajax的根本解决方法,允许任何类型的请求。

客户端和服务器之间使用 CORS 首部字段来处理权限:

先看一个http的请求头和响应头

请求头:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example

请求首部字段 Origin 表明该请求来源于 http://foo.example。而现在的VUE项目中都会默认带上这个请求头。

响应头:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

服务端返回的 Access-Control-Allow-Origin: * 表明,该资源可以被 任意 外域访问,当然,不建议配置 * ,当响应的是附带身份凭证的请求时,即withCredentials为true时,服务端 必须 明确 Access-Control-Allow-Origin 的值,而不能使用通配符“*”。

各个端解决方法:

后端:

后端是基于Springboot开发,提供了这么几种方式来配置 cros

为了灵活配置,先做一个配置文件:application-security.yml

lc:  
   cors:
    allow-credential: true
    allow-mapping: '/**'
    allow-method: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
    allow-origin-pattern: http://192.168.1.11:8101,http://localhost:3002
    allow-header: '*'
    max-age: 1800

properties文件

@Data
@ConfigurationProperties(prefix = "lc.cors")
public class CorsProperties {

    @NotNull
    private Boolean enable = true;

    private String allowMapping;

    private List<String> allowOriginPattern;

    private List<String> allowMethod;

    private List<String> allowHeader;

    @ApiModelProperty("单位:秒")
    private Long maxAge;

    private boolean allowCredential = true;
}

方式1:重载WebMvcConfigurer方法

这种我感觉是最合适的

@Configuration
@EnableConfigurationProperties(CorsProperties.class)
public class CorsConfig {

    @Autowired
    private CorsProperties corsProperties;

    @Bean
    public WebMvcConfigurer corsConfigurer() {

        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {

                registry.addMapping(corsProperties.getAllowMapping())
                        .allowedOriginPatterns(corsProperties.getAllowOriginPattern().toArray(new String[0]))
                        .allowCredentials(corsProperties.isAllowCredential())
                        .allowedMethods(corsProperties.getAllowMethod().toArray(new String[0]))
                        .allowedHeaders(corsProperties.getAllowHeader().toArray(new String[0]))
                        .maxAge(corsProperties.getMaxAge());
            }
        };
    }
}

方式2:配置监听CorsFilter

 @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        return corsConfiguration;
    }

方式3:相关类上加注解 @CrossOrigin


@CrossOrigin
@Controller
@RequestMapping("/problem")
@ResponseBody
public class ProblemController implements Serializable {
 
	
	}

注意事项:

allow-origin-pattern这个属性配置时,尽量不要配置*,也许考虑到联调和线上环境的ip都要添加上

Nginx解决:

nginx解决主要是这个思路,nginx的实际原理就是配置一个代理路径替换实际的访问路径,使得浏览器认为访问的资源都是属于相同协议,域名和端口的,而实际访问的并不是代理路径,而是通过代理路径找到实际路径进行访问,所以,不妨将nginx看作是给浏览器的一种障眼法

情况1:

因为首先访问的是nginx的index.html,这种情况是不会产生跨域问题的,但是访问接口时,因为是调用的后端的接口,所以会产生跨域问题,这时候,我们将所有的接口配置一个代理,转发到实际的后端接口地址。

比如我们nginx配置的前端访问地址为:http://192.168.1.11:8080/api/

                              后端的接口地址为: http://192.168.1.11:8081/api/

下面是nginx的配置文件 nginx.conf,其实就是访问首页时,访问的还是index.html,但是访问具体的url时,nginx帮我们做一层转发,这样子就可以了。也不用加什么【add_header Access-Control-Allow-Origin *;】这样的响应头,因为此时nginx的代理会让浏览器认为是同源的路径

server {
	listen 8101;
	client_max_body_size 20m;
	location / {
		root /usr/share/nginx/html;
		index index.html index.htm;
	}
	location /api/ {
		proxy_pass http://192.168.1.11:8081/api/;
	}
	
}

前端解决:

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

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

相关文章

微信小程序--》你真的了解小程序组件的使用吗?

&#x1f3cd;️作者简介&#xff1a;大家好&#xff0c;我是亦世凡华、渴望知识储备自己的一名在校大学生 &#x1f6f5;个人主页&#xff1a;亦世凡华、 &#x1f6fa;系列专栏&#xff1a;微信小程序 &#x1f6b2;座右铭&#xff1a;人生亦可燃烧&#xff0c;亦可腐败&…

JAVA-分页查询

分页查询 分页查询将数据库中庞大的数据分段显示,每页显示用户自定义的行数,提高用户体验度,最主要的是如果一次性从服务器磁盘中读出全部数据到内存,有内存溢出的风险 真假分页 假分页: 其原理还是将所有的数据读到内存中,翻页从内存中读取数据, 优点: 实现简单,性能高 缺点…

HTML+CSS+JS网页设计期末课程大作业 京剧文化水墨风书画

Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业&#xff0c;茶文化网站 | 中华传统文化题材 | 京剧文化水墨风书画 | 中国民间年画文化艺术网站 | HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作…

EasyExcel复杂表头导出(一对多)升级版

一、前言 在之前写的 EasyExcel复杂表头导出&#xff08;一对多&#xff09;的博客的结尾&#xff0c;受限于当时的能力和精力&#xff0c;留下一些问题及展望。现在写下此博客&#xff0c;目的就是解决之前遗留的问题。 背景介绍&#xff0c;见上述链接指向的博客&#xff0c;…

vue3 route和router的区别以及如何传参数接受参数,如何像vue2一样使用$route和$router详解

vue3 route和router的区别以及如何传参数接受参数&#xff0c;如何像vue2一样使用$route和$router详解 因为我们在 setup 里面没有访问 this&#xff0c;所以我们不能再直接访问 this.$router 或 this.$route。作为替代&#xff0c;我们使用 useRouter 和useRoute函数,或者 Vu…

HTML小游戏21 —— html5版暴打皮卡丘游戏(附完整源码)

&#x1f482; 网站推荐:【神级源码资源网】【摸鱼小游戏】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】本节教程我会带大家使用 HTML…

微信小程序--基础内容(详解)(一)

一、常用标签 1、view 标签 view 标签是一个块级元素&#xff0c;类似于 div&#xff08;小程序里面没有div标签&#xff09;&#xff0c;里面可以放任何内容或者插值表达式&#xff0c;如下所示&#xff1a; <view>这是view标签<view> <view>{{num}}<…

谷歌新版本跨域错误深度剖析与解决:request client is not a secure context and the resource is in more-private address

快速解决&#xff1a; 最近在测试http服务时&#xff0c;谷歌浏览器报了以下错误 “The request client is not a secure context and the resource is in more-private address space ‘local’”. 从报错信息来看&#xff0c;“不安全的请求方请求了更私有的本地资源” 对于…

API接口开发其实特简单,Python Flask Web 框架教程来了

大家好&#xff0c;日常工作中&#xff0c;无论你是数据工程师、数据挖掘工程师&#xff0c;甚至数据分析人员&#xff0c;都不可避免的与他人进行数据交互&#xff0c;API接口提供数据是最常见的形式。 今天我给大家分享 Python Flask Web 框架教程&#xff0c;共计10个部分&…

Vue面试题你知道多少

✅作者简介&#xff1a;大家好我是hacker707,大家可以叫我hacker&#xff0c;新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;带你玩转Vue &#x1f4ac;推荐一款模拟面试、刷题神器&…

前端401错误 解决方法:响应拦截器

目录 1.该问题出现的原因 2.处理401问题的解决方案原理 3.使用响应拦截器解决问题 1.该问题出现的原因 在前后端分离项目中&#xff0c;最常见的是前端点击登录后&#xff0c;后端返回token字符串&#xff0c;这个token可以看作是一个“令牌”&#xff0c;就比如你去酒店办理…

Vue实战【调整Vue-element-admin中的菜单栏,并添加顶部模块菜单栏】

目录&#x1f31f;前言&#x1f31f;小伙伴们先看&#x1f31f;实现思路&#x1f31f;具体代码&#x1f31f;最后&#x1f31f;前言 因为最近在整合公司的项目&#xff0c;需要把所有系统里的功能集成到一个项目里&#xff0c;这样就导致菜单栏目录会特别的多&#xff0c;不便…

【JavaScript】手撕前端面试题:事件委托 | 判断URL是否合法 | 全排列

&#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&#xff09; &#x1f5a5;️ TypeScript知识总结&…

【Axure】Axure RP 9下载、安装、授权、汉化

目录一、Axure RP 9 下载二、Axure RP 9 安装三、Axure RP 9 授权四、Axure RP 9 汉化一、Axure RP 9 下载 1、Axure RP 9 下载地址&#xff1a;https://www.axure.com/release-history/rp9 2、其他版本下载地址 ①登录axure官网:https://www.axure.com/ ②拉到最下面找到相关…

很好看的爱心表白代码(动态)

分享几个好看的爱心表白代码❤️爱心代码❤️&#xff08;C语言&#xff09;❤️流动爱心❤️&#xff08;htmlcssjs&#xff09;❤️线条爱心❤️&#xff08;htmlcssjs&#xff09;❤️biu表白爱心❤️&#xff08;htmlcssjs&#xff09;❤️matlab爱心函数❤️&#xff08;需…

Vue3+TS+Vite 入门指南

最近尝试上手 Vue3TSVite&#xff0c;对比起 Vue2 有些不适应&#xff0c;但还是真香~ 上手前先说下 Vue3 的一些变化吧~ Vue3 的变化 Vue3 带来的变化主要有以下几个方面&#xff1a; 使用层面 对比起 Vue2 启动速度快很多&#xff0c;新项目从 1s 升级到不到 500msvite.co…

Element-UI新手学习记录(一)

Layout 布局 通过基础的 24 分栏&#xff0c;迅速简便地创建布局。 span的作用 一行默认24个span&#xff0c;属性放在el-col中决定此元素占据多少span gutter属性 放在el-row中&#xff0c;给各个块之前设置间隔&#xff0c;但是是割的代码块的宽度。 offset属性 放在el…

小程序页面之间数据传递的四种方法

近期再使用小程序开发的时候遇到小程序页面和页面之间的数据传递问题。总结一下大致有以下几种方式实现页面数据传递。 最常见的就是路由传参&#xff0c;使用场景主要是页面汇总的少量数据的传递。以下都以Tarovue示例&#xff0c;原生、react或者uniapp同理&#xff0c;替换…

Pinia(二)了解和使用Store

Store Store 是保存状态(state)和业务逻辑的实体, store 不应该与我们的组件绑定. 换句话说, store 就是全局状态.store 有三个关键概念, 分别是 state, getters 和 actions, 这与 Vue 组件中的 data, computed 和 methods 是相对应的概念. 定义 store 通过 defineStore 函数…

Vue页面路由参数的传递和获取

文章目录1. 通过动态路由参数传递2. 通过query字符串传递3. props 隐式传递vue 页面路由切换时传参的方式有如下几种&#xff1a; 动态路由参数 它隐藏字段信息&#xff0c;相对于来说较安全&#xff0c;同时地址栏中的地址也相对较短 它必须是先定义后使用&#xff0c;一般用…