CORS-跨域资源共享

news2024/11/20 1:22:47

CORS-跨域资源共享

什么是CORS ?

在前后端分离的项目中,我们往往会遇到跨域问题。

跨域问题只会出现在浏览器发起AJAX(XMLHttpRequest、Fetch)请求的时候,因为浏览器限制了AJAX只能从同一个源请求资源,除非配置了正确的CORS。

CORS被翻译为跨域资源共享(或者跨源资源共享),是一种基于HTTP头的机制,该机制允许服务器标识除自己以外的,使得浏览器允许这些源访问自己的资源。

源就是指请求URL中的协议、域名、端口号

image-20240725143635339

当请求发起者与接收者的协议、域名、端口号三者有任一个不同时即为跨域(跨源),就发生了CORS。

请求发起者请求接受者是否跨域原因
http://www.test.com/http://www.test.com/index.html同源
http://www.test.com/https://www.test.com/协议不同(http、https)
http://www.test.com:8080/http://www.test.com:8088/端口不同(8080、8088)
http://www.test.com/http://www.tesT.com/同源
http://www.a.com/http://www.b.com/域名不同(a、b)

CORS 又分为简单请求和非简单请求

简单请求

在HTML中一般可以通过元素发起简单请求。

简单请求需满足以下条件:

  • 使用以下请求方法之一:
    • HEAD
    • POST
    • GET
  • 除自动配置的标头字段外,仅可人为配置以下字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type
    • Range
  • Content-Type设置的媒体类型仅限以下类型:
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 如果请求是使用XMLHttpRequest对象发出的,在返回的XMLHttpRequest.upload对象属性上没有注册任何事件监听器
  • 请求中没有使用ReadableStream对象

非简单请求

非简单请求需要在发送实际请求之前使用OPTIONS方法发送一个预检请求,以获知服务器是否允许该实际请求,避免实际的跨域请求对用户数据产生影响。

Nginx解决跨域问题

使用Nginx反向代理解决跨域问题是较为简单的解决办法,只需要配置nginx.conf配置文件即可:

server {
    #nginx监听所有localhost:8080端口收到的请求
	listen       8080;
	server_name  localhost;
 
	# Load configuration files for the default server block.
	include /etc/nginx/default.d/*.conf;
	
    #localhost:8080 会被转发到这里
	#同时, 后端程序会接收到 "192.168.25.20:8088"这样的请求url
	location / {
		proxy_pass http://192.168.25.20:8088;
	}
	
	#localhost:8080/api/ 会被转发到这里
    #同时, 后端程序会接收到 "192.168.25.20:9000/api/"这样的请求url
	location /api/ {
		proxy_pass http://192.168.25.20:9000;
	}
	
	error_page 404 /404.html;
		location = /40x.html {
	}
	
	error_page 500 502 503 504 /50x.html;
		location = /50x.html {
	}
}

Spring 解决跨域问题

WebMvcConfigurer

可以通过重写WebMvcConfigurer中的***addCorsMappings(CorsRegistry registry)***方法来配置全局跨域设置:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")                  // 允许跨域请求的path,支持路径通配符,如:/api/**
            .allowedOrigins("*")                    // 允许发起请求的源
            .allowedHeaders("*")                    // 允许客户端的提交的 Header,通配符 * 可能有浏览器兼容问题
            .allowedMethods("GET")                  // 允许客户端使用的请求方法
            .allowCredentials(false)                // 不允许携带凭证
            .exposedHeaders("X-Auth-Token, X-Foo")  // 允许额外访问的 Response Header
            .maxAge(3600)                           // 预检缓存一个小时
            ;
    }
}

@CrossOrigin

为了更精确的配置跨域,可以在Controller类或其方法上添加注解***@CrossOrigin***

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/foo")
@RestController
@CrossOrigin(
    	origins = "*",             // 允许的源,也就是 allowedOrigins
        allowCredentials = "false",     // 不允许提交cookie
        allowedHeaders = "*",           // 允许的请求头
        exposedHeaders = "*",           // 允许客户端额外读取的响应头
        maxAge = 3600,                  // 缓存时间
        methods = {RequestMethod.GET, RequestMethod.HEAD} // 允许客户端的请求方法
)
public class FooController {
    
}

CorsFilter

不管是WebMvcConfigurer还是**@CrossOrigin**都是硬编码的方式,不够灵活。

Spring提供了一个CorsFilter让我们以编程式的方式更灵活的配置跨域。

import java.time.Duration;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer{

    // 通过 FilterRegistrationBean 注册 CorsFilter
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        
        // 跨域 Filter
        CorsFilter corsFilter = new CorsFilter(request -> {
            
            // 请求源
            String origin = request.getHeader(HttpHeaders.ORIGIN);
            
            if (!StringUtils.hasText(origin)) {
                return null; // 非跨域请求
            }
            
            // 针对每个请求,编程式设置跨域
            CorsConfiguration config = new CorsConfiguration();
            
            // 允许发起跨域请求的源,直接取 Origin header 值,不论源是哪儿,服务器都接受
            config.addAllowedOrigin(origin);
            
            
            // 允许客户端的请求的所有 Header
            String headers = request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
            if (StringUtils.hasText(headers)) {
                config.setAllowedHeaders(Stream.of(headers.split(",")).map(String::trim).distinct().toList());
            }
            
            // 允许客户端的所有请求方法
            config.addAllowedMethod(request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD));
            // 允许读取所有 Header
            // 注意,"*" 通配符,可能在其他低版本浏览中不兼容。
            config.addExposedHeader("*");
            // 缓存30分钟
            config.setMaxAge(Duration.ofMinutes(30));
            // 允许携带凭证
            config.setAllowCredentials(true);
            return config;
        });
        
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(corsFilter);
        bean.addUrlPatterns("/*");                  // Filter 拦截路径
        bean.setOrder(Ordered.LOWEST_PRECEDENCE);   // 保证最先执行
        return bean;
    }
}

不管是什么方式,当allowCredentials为true允许携带凭证时,allowedOrigins不能再使用通配符“*”,必须填写确切的源。

凭证通常是包含用户标识的Cookie

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

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

相关文章

DeadSec CTF 2024 Misc Writeup

文章目录 MiscWelcomeMic checkflag_injectionGoLPartyMAN in the middleForgotten Password CryptoFlag killer 好久没做这么爽了噜 DK盾云服务器&#xff1a; https://www.dkdun.cn/ 最近活动是香港的1-1-3 9.9/月 Misc Welcome 进discord群签到即可 Mic check 就是他说…

echarts所遇到的问题,个人记录

TreeMap 矩形树图&#xff0c;label设置富文本之后&#xff0c;无法垂直居中 font-size 支持rem&#xff0c;其余不支持 font-size 支持 rem&#xff0c;但是其余的属性如height&#xff0c;width等不支持 echarts-for-react 绑定事件&#xff0c;会覆盖实例上绑定的 当给cha…

通过服务端注入的广告被拦截 YouTube现在可能会出现黑屏静音视频段

为避免用户使用广告拦截程序直接拦截 YouTube 平台的所有广告&#xff0c;这段时间谷歌正在采取各种措施与社区进行技术对抗&#xff0c;即谷歌不停地开发新的广告检测方式阻止用户使用广告拦截程序&#xff0c;广告拦截程序则不停地开发应对方法用来继续屏蔽广告和各种提示。 …

uni-app全局文件与常用API

文章目录 rpx响应式单位import导入css样式及scss变量用法与static目录import导入css样式uni.scss变量用法 pages.json页面路由globalStyle的属性pages设置页面路径及窗口表现tabBar设置底部菜单选项及iconfont图标 vite.config中安装插件unplugin-auto-import自动导入vue和unia…

AJAX(2)——URL

URL 什么是URL&#xff1f; 定义&#xff1a;统一资源定位符&#xff0c;缩写&#xff1a;URL&#xff0c;或称统一资源定位器、定位地址&#xff0c;URL地址,俗称网页地址&#xff0c;简称网址&#xff0c;是因特网上标准的资源的地址。 概念&#xff1a;URL就是统一资源定…

Linux下C++动态链接库的生成以及使用

目录 一.前言二.生成动态链接库三.使用动态链接库 一.前言 这篇文章简单讨论一下Linux下如何使用gcc/g生成和使用C动态链接库&#xff08;.so文件&#xff09;。 二.生成动态链接库 先看下目录结构 然后看下代码 //demo.h#ifndef DEMO_H #define DEMO_H#include<string&…

【C++】C++应用案例-检验幻方

“幻方”是数学上一个有趣的问题&#xff0c;它让一组不同的数字构成一个方阵&#xff0c;并且每行、每列、每个对角线的所有数之和相等。比如最简单的三阶幻方&#xff0c;就是把1~9的数字填到九宫格里&#xff0c;要求横看、竖看、斜着看和都是15。 口诀&#xff1a;二四为肩…

Pip换源实战指南:加速你的Python开发

1. Pip换源的重要性 在使用Python进行软件开发或数据分析时&#xff0c;pip 是Python的包管理工具&#xff0c;用于安装和管理第三方库。然而&#xff0c;由于网络环境的差异&#xff0c;特别是在某些国家&#xff0c;访问默认的PyPI&#xff08;Python Package Index&#xff…

debain12中安装mysql8

本文安装使用的官方deb&#xff0c;最新的官方安装包地址&#xff1a;https://repo.mysql.com/mysql-apt-config_0.8.29-1_all.deb 前期准备&#xff1a; 1.安装了debain12.6的虚拟机&#xff0c;我是用的virtualBox安装的12.6 Edu的镜像&#xff1b; 开始安装&#xff1a; …

微服务的入门

带着问题进行学习&#xff1a; 1. 对服务进行拆分后&#xff0c;物理上是隔离的&#xff0c;数据上也是隔离的&#xff0c;如何进行不同服务之间进行访问呢&#xff1f; 2.前端是怎么样向后端发送请求的&#xff1f; 通过http请求&#xff0c;通过url&#xff0c;请求的…

最新版Golang pprof使用(引入、抓取、分析,图文结合)

最新版Golang pprof使用 &#x1f525;具体实践: Go调试神器pprof使用教程Golang线上内存爆掉问题排查&#xff08;pprof&#xff09; Github地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-pprof 引入pprof:import _ “net/http/pprof” …

python 查询机器python、gpu、安装包等环境版本信息

checkenv.py """Check environment configurations and dependency versions."""import importlib import os import resource import subprocess import sys from collections import OrderedDict, defaultdictimport torch# 查询自己想要的包…

【开源】一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。

基于 LLM 大语言模型的知识库问答系统 基于大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的知识库问答系统是一种利用先进的自然语言处理技术来理解用户查询并从知识库中检索出准确答案的系统。这里的LLM指的是能够处理和理解大量文本数据的人工智能…

【Go - 如何查看类型,运行前/运行时】

方式1 - 运行时查看 在Go中&#xff0c;你可以使用reflect.TypeOf()函数来获取变量的类型。这需要导入reflect包。以下是个示例&#xff0c;在运行时打印变量的类型&#xff1a; package mainimport ("context""fmt""reflect""go.mongodb…

精通推荐算法13:图神经网络之GraphSAGE

1 引言 近年来&#xff0c;图神经网络&#xff08;Graph Neural Networks&#xff0c;GNN&#xff09;在NLP、风控和推荐系统等领域的研究十分火热&#xff0c;其对推荐系统、生物医药、社交网络和知识图谱等非结构化数据有十分优秀的处理能力。基于图神经网络的Embedding表征…

用户登录安全是如何保证的?如何保证用户账号、密码安全?

1.HTTP协议直接传输密码&#xff08;无加密&#xff09; 前端 直接发送HTTP请求&#xff08;无加密&#xff09;&#xff0c;攻击者可直接捕获网络包&#xff0c;看到下面的明文信息 因此&#xff0c;使用HTTP协议传输会直接暴露用户敏感信息。 2.HTTPS协议直接传输密码&…

windows环境 python + opencv 加载 onnx 人脸检测模型识别人脸测试

参考博客&#xff1a; 1. OpenCV-Python 4.5.4 人脸识别应用&#xff1a;https://blog.csdn.net/qq_36563273/article/details/121510440( 代码就是在此博客代码基础上改的&#xff0c;主要添加了人脸画框的逻辑 ) 1. windows环境&#xff1a;win11 2. 安装 miniconda2-4.7.1…

用python解释进程与协程(python实例二十八)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.创建进程池&#xff0c;异步执行多个任务 3.1 代码构思 3.2 代码示例 3.3 运行结果 4. 模拟协程堵塞 4.1 代码构思 4.2 代码示例 4.3 运行结果 5.总结 1.认识Python Python 是一个高…

算法019:x的平方根

x的平方根. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/sqrtx/ 这个题乍一看很奇怪&#xff0c;但是换个角度&#xff0c;我们用二分查找的思想来完成这个题。 …

组队学习——决策树(以泰坦尼克号公共数据集为例)

本次我们挑战的数据集为泰坦尼克号公共数据集&#xff0c;为了降低难度&#xff0c;我们在原有数据集的基础上进行了优化&#xff0c;具体数据集介绍如下&#xff1a; 在这里也介绍一下数据的含义吧 数据介绍&#xff1a; Survived&#xff1a;是否存活&#xff08;label&#…