记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑
我通过这篇文章把今天工作中遇到的HTTP跨域和OPTION请求的一个坑记录下来。
场景是我需要在部署在域名a的Web应用里用JavaScript去消费一个部署在域名b的服务器上的服务。域名b上的服务也是我开发的,因此我将域名a加到了该服务的HTTP响应结构的头文件里,这样就允许了域名a上的JavaScript代码用AJAX访问域名b的服务。
域名b上的服务是一个Servlet,允许域名a跨域访问的代码就一行:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 做业务逻辑response.setHeader("Access-Control-Allow-Origin", "域名a");}
我在域名a的Web应用里用AJAX发起服务请求:
执行后,发现并没有显示200的弹出窗口。
错误消息:Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
观察Chrome开发者工具,发现其实域名b的服务已经成功执行了,确实返回了200的Status code,
而且我已经从Chrome开发者工具里观察到浏览器已经成功接到域名b发送回来的请求了。
那这个错误是什么鬼呢?根据错误消息“Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response” Google了一下,发现一些朋友遇到同样的问题:
1. 如何解决出现AXIOS的Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
网页地址: https://www.cnblogs.com/caimuqing/p/6733405.html
这位朋友的解决方案:
response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Credentials", "true");response.setHeader("Access-Control-Allow-Methods", "*");response.setHeader("Access-Control-Allow-Headers", "Content-Type,Access-Token");response.setHeader("Access-Control-Expose-Headers", "*");if (request.getMethod().equals("OPTIONS")) {HttpUtil.setResponse(response, HttpStatus.OK.value(), null);return;}
但我试过,在我的场景下还是不工作,因为我的例子里,服务器已经针对OPTIONS请求返回HTTP 200的状态码了。
2. 这个Stackoverflow的帖子里,很多朋友都提供了自己的解决方案。
https://stackoverflow.com/questions/42061727/cors-error-request-header-field-authorization-is-not-allowed-by-access-control/42061962
我一一试过,在我的场景里都不能工作。
于是我查询了Mozilla的一篇文档:HTTP访问控制(CORS)
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
里面谈到了,在某些情况下,浏览器在发起“需要预检的请求”之前,必须首先发起一个“预检请求(Preflight)”到服务器,以探测服务器是否允许这个实际请求。"预检请求"机制的使用,是为了避免跨域请求对服务器的用户数据产生未预期的影响。
那么哪些请求算作“需要预检的请求”呢?Mozilla的这篇文档定义得很清楚:
当请求满足下述任一条件时,即应首先发送预检请求:
- 使用了下面任一 HTTP 方法:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type 的值不属于下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
我再检查我的代码,因为我在HTTP请求里用xhr.setRequestHeader(“Authorization”, “用户名:密码的base64编码” )添加了用于Basic Authentication的头部,因此迫使该请求成为了“需要预检的请求”,所以才有了OPTION请求的发送。
现在我将其注释掉:
这次遇到了401 Unauthorized错误了:
然而没有预检请求OPTION发出来了,请求类型变成了我期望的POST方式了。
但是现在就陷入了一个矛盾的境地:如果在请求头部加上Basic Authentication的信息,会遇到错误消息“Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.”。如果去掉,虽然避免了预检请求,但是又遇到401 Unauthorized错误了。
于是,我换了一种认证方式,终于成功实现了期望的跨域请求,在我域名a的前端应用里打印出了来自于域名b的服务的响应。
我使用了form认证方式,这种方式不会造成该请求成为一个”需要预检的请求“,所以最后跨域成功了。
var formData = new FormData();formData.append('sap-client', "001");formData.append('sap-user', "用户名");formData.append('sap-password', "用户密码");var request = new XMLHttpRequest();request.open("POST", "域名b的url",false);request.send(formData);alert("response: " + request.responseText);
希望我的这个踩坑经历对大家有点帮助。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑相关推荐
- mui后端开发php,PHP解决mui中ajax的跨域问题
什么是跨域访问 在A网站中,我们希望使用Ajax来获得B网站中的特定内容.如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题.你可以理解为两个域名之间不能跨过域名来发送请求或者请求数据,否则就 ...
- 开发中解决Access-Control-Allow-Origin跨域问题的Chrome神器插件,安装及使用
开发中解决Access-Control-Allow-Origin跨域问题的Chrome神器插件,安装及使用 参考文章: (1)开发中解决Access-Control-Allow-Origin跨域问题的 ...
- 一步步教你前端vue项目开发中如何解决跨域问题
文章目录 开发环境中跨域 名词解释 1.同源策略: 2.同源: 3.跨域: 4.代理服务器: 解决方式 项目背景 跨域配置 1.配置说明: A.参数proxy详解: B.pathRewrite详解: ...
- J2EE开发工作中遇到的异常问题及解决方法总结
J2EE开发工作中遇到的异常问题及解决方法总结 参考文章: (1)J2EE开发工作中遇到的异常问题及解决方法总结 (2)https://www.cnblogs.com/shinubi/p/450715 ...
- Spring Boot 中三种跨域场景总结
文章目录 1.什么是跨域 2.解决方案 2.1 存在的问题 3.SpringSecurity 3.1 方式一 3.2 方式二 4.OAuth2 5.小结 跨域这个问题松哥之前写过文章,但是最近收到小伙 ...
- 记录一次若依框架 前端跨域访问 ruoyi -vue
Ruoyi -vue 若依框架 前端跨域访问 总的思路 创建一个用于第三方平台使用的request拦截器,并定义一个新的path ,最后配置 deserver,其实网上也有很多 对于我这样JAVA开发 ...
- ssm把图片保存到项目中_项目中的图片跨域问题解决方式
现象 首先,在生产环境中,由于进行编辑图片时,将图片回显到ReactCrop组件中进行可裁剪编辑,然而回显时,需要将图片转化为base64的格式或者blob对象, 此时需要将图片次绘制成canvas进 ...
- 【全栈项目上线(vue+node+mongodb)】06.nodejs服务上线(生产环境前后分离的vue项目中怎么解决跨域问题)...
以下操作使用下面项目为案例 https://github.com/itguide/vnshop ## 启动node服务 克隆好项目后记得把依赖包安装好 npm i 使用 node 启动node服务 c ...
- Android中WebView的跨域漏洞分析和应用被克隆问题情景还原(免Root获取应用沙盒数据)...
一.前言 去年年底支付宝的被克隆漏洞被爆出,无独有偶就是腾讯干的,其实真正了解这个事件之后会发现,感觉是针对支付宝.因为这个漏洞找出肯定花费了很大劲,主要是因为支付宝的特殊业务需要开启了WebView ...
最新文章
- exist not exist 分析
- zynq交叉编译环境
- win7下不能使用dnw烧写的解决办法——韦东山嵌入式Linux学习笔记05
- 使用Spring Security3的四种方法概述
- python基础知识点制作图片
- [MEGA DEAL] Ultimate SQL Bootcamp认证捆绑包(98%)
- 使用Fabric8在CDI管理的bean中注入Kubernetes Services
- android switch 未定义,在switch语句中初始化时未定义的变量?
- Swift快速参考手册
- 可拖动的进度条_TIM iOS版重大更新:支持语音进度条拖动和暂停
- 可逆加密,支持中文,支持密钥,加密后的密文每次都不同,且可随意改变算法 组件之Vb.Net版本...
- java删除文件夹及其内部文件
- python怎么读单词和古文_Python 实现文言文词频统计
- 科研项目研究的基本步骤
- 基于OpenCASCADE自制三维建模软件(一)介绍
- ROS moveit cartesian_demo 机械臂笛卡尔空间路径速度限制
- html 去掉html超链接下划线
- 微信小程序picker 组件自定义三级联动
- Android 疑难杂症系列
- uniapp 调用安卓原生插件 安卓原生又调用了第三方sdk(第三方原生开发的aar怎么转成uni可以使用的aar)
热门文章
- 聚类算法(part1)--DBSCAN
- @transactional 接口_Spring事物(@transactional注解)在什么情况下会失效,为什么?...
- ts-node 学习笔记 - 如何解决在 Windows10 下不能直接运行 ts-node 的问题
- SAP Spartacus Header 区域的默认配置
- SAP Spartacus 和 SmartEdit 协同工作需要遵循的协议
- 关于windows的version和OS build version
- Angular export class AppComponent里定义变量的实现原理
- 如何查看SAP云平台上某个subaccount的tenant和region信息
- 如何去除Eclipse Maven插件里关于Managed version的警告消息
- SAP UI5 oSelectedItem.getBindingContext(json)