CORS解决跨域问题

2023-11-08

1.跨域问题

1.1 什么是跨域

跨域是指跨域名的访问,以下情况都属于跨域:

跨域原因说明 示例
域名不同 www.jd.comwww.taobao.com
域名相同,端口不同 www.jd.com:8080www.jd.com:8081
二级域名不同 item.jd.commiaosha.jd.com

如果域名和端口都相同,但是请求路径不同,不属于跨域,如:

www.jd.com/item

www.jd.com/goods

定义:跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。

1.2 为什么有跨域问题?

跨域不一定会有跨域问题。

因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。

例如:一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。比如下面的操作就有安全问题:

  1. 用户访问www.mybank.com ,登陆并进行网银操作,这时cookie啥的都生成并存放在浏览器
  2. 用户突然想起件事,并迷迷糊糊地访问了一个邪恶的网站 www.xiee.com
  3. 这时该网站就可以在它的页面中,拿到银行的cookie,比如用户名,登陆token等,然后发起对www.mybank.com 的操作
  4. 如果这时浏览器不予限制,并且银行也没有做响应的安全处理的话,那么用户的信息有可能就这么泄露了。

因此:跨域问题 是针对ajax的一种限制

1.3 解决跨域问题的方案

目前比较常用的跨域解决方案有3种:

  • Jsonp

    最早的解决方案,利用script标签可以跨域的原理实现。

    限制:

    • 需要服务的支持
    • 只能发起GET请求

    Jsonp原理与实践

  • nginx反向代理

    思路是:利用nginx反向代理把跨域为不跨域,支持各种请求方式

    缺点:需要在nginx进行额外配置,语义不清晰

  • CORS

    规范化的跨域请求解决方案,安全可靠。

    优势:

    • 在服务端进行控制是否允许跨域,可自定义规则
    • 支持各种请求方式

    缺点:

    • 会产生额外的请求

我们这里会采用cors的跨域方案。

2 cors解决跨域

2.1 什么是cors

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

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

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

  • 浏览器端:

    目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。

  • 服务端:

    CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,我们需要以此判断是否运行其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。

2.2 原理

浏览器会将ajax请求分为两类,其处理方案略有差异:简单请求、特殊请求。

2.2.1 简单请求

只要同时满足以下两大条件,就属于简单请求。:

(1) 请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

当浏览器发现发现的ajax请求是简单请求时,会在请求头中携带一个字段:Origin.

Origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

如果服务器允许跨域,需要在返回的响应头中携带下面信息:

Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
  • Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*,代表任意
  • Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

注意:

如果跨域请求要想操作cookie,需要满足3个条件:

  • 服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
  • 浏览器发起ajax需要指定withCredentials 为true
  • 响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

2.2.2 特殊请求

不符合简单请求的条件,会被浏览器判定为特殊请求,,例如请求方式为PUT。

预检请求

特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

一个“预检”请求的样板:

OPTIONS /cors HTTP/1.1
Origin: http://manage.leyou.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.leyou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

与简单请求相比,除了Origin以外,多了两个头:

  • Access-Control-Request-Method:接下来会用到的请求方式,比如PUT
  • Access-Control-Request-Headers:会额外用到的头信息

预检请求的响应

服务的收到预检请求,如果许可跨域,会发出响应:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

除了Access-Control-Allow-OriginAccess-Control-Allow-Credentials以外,这里又额外多出3个头:

  • Access-Control-Allow-Methods:允许访问的方式
  • Access-Control-Allow-Headers:允许携带的头
  • Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了

如果浏览器得到上述响应,则认定为可以跨域,后续就跟简单请求的处理是一样的了。

2.3 实现非常简单

虽然原理比较复杂,但是前面说过:

  • 浏览器端都有浏览器自动完成,我们无需操心
  • 服务端可以通过拦截器统一实现,不必每次都去进行跨域判定的编写。

事实上,SpringMVC已经帮我们写好了CORS的跨域过滤器:CorsFilter ,内部已经实现了刚才所讲的判定逻辑,我们直接用就好了。

Application下编写一个配置类,并且注册CorsFilter:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了
        config.addAllowedOrigin("http://manage.leyou.com");
        //2) 是否发送Cookie信息
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        // 4)允许的头信息
        config.addAllowedHeader("*");

        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

结构:

放到Application下即可。

4.5.4.重启测试:

访问正常:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CORS解决跨域问题 的相关文章

  • 创建 RESTful WebService 并通过 Glassfish 4 提供服务

    我在 JEE6 中看到了很多关于 RESTful WebServices 的问题 所以我想与您分享这个示例解决方案 它展示了实现 RESTful Webservice 是多么容易 首先创建一个新的动态 Web 项目并将 Glassfish
  • 我的应用程序中的 google+ 集成

    我是 Android 开发新手 正在创建一个带有 Google 集成的 Android 应用程序 我看到了一个教程并开始遵循它 但自教程以来 Google 已经更新了 Google 集成 例如 在本教程中您曾经单击 获取配置文件 按钮htt
  • Eclipse + Spring Boot 中“抛出 new SilentExitException()”处的断点

    每次我在 Eclipse IDE Spring Tool Suite 中以调试模式运行 Spring Boot 项目时 线程都会停止在throw new SilentExitException 即使没有断点也行 有什么解决方案可以避免这种行
  • 有没有办法获取 JList 中的所有元素?

    我想知道是否有一种方法可以检索已添加到 JList 的所有元素的列表 例如 我希望 JList 从自定义单元格渲染器返回字符串或 JLabels 的数组或列表 您可以使用getModel http docs oracle com javas
  • 为什么在Java中读取易失性和写入字段成员是不可扩展的?

    观察以下用 Java 编写的程序 完整的可运行版本如下 但程序的重要部分在下面的代码片段中 import java util ArrayList A not easy to explain benchmark class MultiVola
  • 通过标记或JS强制下载

    假设我在 CDN 来自 Rackspace 的云文件 上有一个文件 以及一个包含该文件链接的静态 html 页面 有什么方法可以强制下载此文件 以防止它在浏览器中打开 例如 mp3 我们可以让我们的服务器读取该文件并将相应的标头设置为 he
  • 如何将堆栈跟踪转换为字符串?

    转换结果的最简单方法是什么Throwable getStackTrace 到描述堆栈跟踪的字符串 Use Throwable printStackTrace PrintWriter pw https docs oracle com java
  • 使用 Hibernate/Spring 生成数据库更新脚本

    我有一个项目 我们过去依赖 hibernate 来更新数据库 hibernate hbm2ddl auto update 即使在产品上 我正在将其迁移为使用 liquibase 我唯一担心的是 并不是我的团队中的每个人都是 sql 专家 因
  • 获取 Spring Boot 中当前活动数据源的引用

    我想通过实现数据库数据初始化DataSourceInitializer 我将这些方法放在我的 Spring Boot 主方法下面 但似乎它根本没有被执行 我尝试故意删除字符只是为了触发一个错误来确认执行 什么也没有发生 Configurat
  • 使用 Hashmap 理解两个或多个键

    我的哈希图有问题 在我的哈希映射方法中 我希望有两个或多个关键字作为键 而不是只有一个 例如 我希望用户输入一些包含两个或多个关键字的句子 假设 教授姓名 是关键字 例如 String temp3 instructor teacher me
  • Java 1.8 和 tomcat 6.0.53 引起:java.io.EOFException:SSL 对等点错误关闭

    java cp catalina jar org apache catalina util ServerInfo Server version Apache Tomcat 6 0 53 Server built Apr 19 2017 22
  • 面临 process.start(); 的问题在 Android 棒棒糖中

    面临一个问题process start 在 Android 棒棒糖中 我在服务中遇到了 android lollipop 后台进程的问题 我的代码在 KitKat 之前工作正常 我有一个ProcessBuilder pBuilder并向其中
  • 为什么 (Oracle) JVM 对内存使用有固定上限 (-Xmx)?

    本着提问的精神Java 为什么存在 MaxPermSize https stackoverflow com questions 3356005 java why does maxpermsize exist 我想问一下为什么Oracle J
  • Java SFTP使用JSch上传,但如何覆盖当前文件?

    我正在尝试使用 JSch 通过 SFTP 将两个文件上传到服务器 如果目录为空 则上传文件效果很好 但我想一遍又一遍地上传相同的文件 只需更改内部的 id 但我不知道如何执行此操作 JSch 中有一些名为 OVERWRITE 的静态参数 但
  • SQLite适合并发读吗?

    在没有锁定的情况下 SQLite 数据库的性能是否能达到每秒 50 次读取左右 我正在尝试确定它是否可以在不会经常 写入 的 PHP 网站上使用 它主要是从一小部分表中读取相同的数据 没问题 并发读 写实际上会被 SQLite 序列化 所以
  • 如何显示 javadoc 代码块中的泛型?

    我有一个 javadoc 代码块 我想在其中编写一个包含泛型的代码示例 如下所示 public interface SomeInterface
  • 在java中访问dll方法

    我正在尝试访问java中用c 编写的dll方法 从下面的代码我试图构建已成功生成的 dll using System using Microsoft Win32 namespace CyberoamWinHelper public clas
  • GridLayout 中的 JLabel

    如何添加JLabel出于GridLayout 我有一个 8x8 网格布局 Container content getContentPane content setLayout new GridLayout 8 8 2 2 for int f
  • Java中ThreadFactory的使用

    有人可以简要解释一下如何以及何时使用 ThreadFactory 吗 使用和不使用 ThreadFactory 的示例可能确实有助于理解差异 Thanks 这是一种可能的用法 假设您有一个ExecutorService它执行你的Runnab
  • JFrame.repaint() 和 JPanel.repaint() 之间的区别

    谁能解释一下两者之间的区别JPanel repaint 方法和JFrame repaint 方法 我想两者都调用paintComponent JPanel 中的方法 请澄清 谢谢 Calling repaint 在任何组件上都会向重绘管理器

随机推荐

  • 学习笔记:进程间通信

    进程间通信的方式 示例 管道的概念及使用 管道pipe详解点击此处 示例 注 写端fd 1 读端fd 0 创建共享内存 mmap函数 思考 总结 示例 mmap父子进程通信 匿名映射 示例 进程1 进程二 shmget函数和mmap的区别
  • 逆矩阵的概念与性质

    逆矩阵的概念与性质 定理1 若矩阵A是可逆的 则A的逆矩阵是唯一的 并记作A的逆矩阵为A 1 性质 定理3 设A为n阶矩阵 则下列各命题等价 1 A是可逆的 2 AX 0只有零解 3 A与I行等价 4 A可表为有限个初等矩阵的乘积 注意 初
  • Docker的概念(1)

    前置条件 需要掌握Linux及常用命令 目录 1 Docker是什么 2 Docker用途 3 Docker与虚拟化 4 Docker和一个正常的虚拟机有何区别 5 Docker虚拟化的好处 5 1 应用部署方便 5 2 服务器同等配置 性
  • NDK开发——FFmpeg实现视频转YUV、视频转RGB显示、音频转PCM、音频播放、音视频同步

    项目演示 前提准备 编译FFmpeg CMake并能运行 详细可见我博客 下载libyuv库并编译成libyuv so库 用于实现转换RGB格式功能 FFmpeg库简介 avcodec 编解码 包含 avformate 封装格式处理 avf
  • Linux makefile 教程 非常详细,且易懂

    最近在学习Linux下的C编程 买了一本叫 Linux环境下的C编程指南 读到makefile就越看越迷糊 可能是我的理解能不行 于是google到了以下这篇文章 通俗易懂 然后把它贴出来 方便学习 后记 看完发现这篇文章和 Linux环境
  • 烟雾调节器

    先看效果 烟雾调节展示 再看代码
  • 【深度学习基础】损失函数

    深度学习基础 性能评估指标 超参数介绍 损失函数 前言 本文主要总结一下常见目标检测的损失函数以及一些基础的函数 主要损失函数为mask rcnn涉及到的损失函数包括 MSE均方误差损失函数 Cross Entropy交叉熵损失函数 目标检
  • Java项目:设计管理系统(java+SSM+JSP+MYSQL+layui+Maven)

    源码获取 博客首页 资源 里下载 一 项目简述 功能包括 课题管理 学生管理 内容管理 文件管理 提问管理 教师管理 进度管理等等 二 项目运行 环境配置 Jdk1 8 Tomcat8 5 mysql Eclispe IntelliJ ID
  • 新规明确所有APP必须备案!附备案指引

    2023年8月底前 新APP需要先备案才能上线 2024年4月前 存量APP完成备案 未履行备案手续的 不得从事APP互联网信息服务 网络接入服务提供者 分发平台 智能终端生产企业不得为未履行备案手续的APP提供网络接入 分发 预置等服务
  • SQL server 安装问题

    安装sqlserver2008中遇到的一些问题和解决办法 安装过程中遇到restart computer 导致不能成功安装 解决办法 1 打开注册表编辑器 2 找到以下路径 HKEY LOCAL MACHINE SYSTEM Current
  • 2020蓝桥杯省赛Java B组一等奖

    大家觉得写还可以 可以点赞 收藏 关注一下吧 也可以到我的个人博客参观一下 估计近几年都会一直更新 和我做个朋友吧 https motongxue cn 文章目录 A 门牌制作 问题描述 答案提交 代码 B 寻找 2020 问题描述 答案提
  • php用session防CC

  • 带头双向循环链表的增删查改

    带头双向循环链表的增删查改 简介 首先我们来看一下带头双向循环链表的结构示意图 在实际内存中并非是这样的结构 画图是为了我们能更好的理解链表 带头双向循环链表的结构最复杂 一般用在单独存储数据 实际中使用的链表数据结构 都是带头双向循环链表
  • 多机器人路径规划算法及其在CVD算法下的实现

    多机器人路径规划算法及其在CVD算法下的实现 在多机器人协同工作的场景中 路径规划问题是非常重要的 而对于存在障碍物的情况下 Voronoi图算法可以用于寻找机器人的最佳路径 本文将介绍一种基于CVD算法的多机器人路径规划算法 并提供相应的
  • 【MVCC多版本并发控制】MVCC 机制的原理及实现,什么是MVCC,多版本并发控制

    什么是 MVCC MVCC Multiversion Concurrency Control 中文全程叫多版本并发控制 是现代数据库 包括 MySQL Oracle PostgreSQL 等 引擎实现中常用的处理读写冲突的手段 目的在于提高
  • no matching key exchange method found

    问题描述 今天升级Ubuntu系统到16 04之后 之前通过git管理的一个项目add和commit之后无法push到服务器 每次提交都报以下错误 Unable to negotiate with xx xx x xxx port xxxx
  • 2021年数学建模国赛C题问题二详细思路和代码

    2021年数学建模国赛C题问题一详细思路和代码 说明 本思路仅为小编个人思路 其中关于本文中给出的AdaBoost回归预测模型于今年的 国赛参考评分标准有所出入 所以本题思路为个人创新思路 不一定符合评分标准 符号说明 1 问题分析 问题二
  • 深度学习学习日记_FCN_(1) shift_and_stitch

    当网络最后一层输出的 prediciton map size 和 label map size 大小不匹配时 除了bilinea interpolation 等暴力措施 且不采取 unpooling deconvolution 等decod
  • [Shell]文本处理工具(grep,cut,sort,uniq,tee,diff,paste,tr)以及bash的特性

    Shell 提示 Shell脚本基础 第一章 文本处理工具以及bash的特性 文章目录 Shell TOC 文章目录 前言 一 文本处理工具 1 grep工具 2 cut工具 3 sort工具 4 uniq工具 二 使用步骤 1 引入库 2
  • CORS解决跨域问题

    1 跨域问题 1 1 什么是跨域 跨域是指跨域名的访问 以下情况都属于跨域 跨域原因说明 示例 域名不同 www jd com 与 www taobao com 域名相同 端口不同 www jd com 8080 与 www jd com