【前端】为什么postman可以请求成功,并且GET请求没有问题,但是POST访问却是403?

avatar
作者
筋斗云
阅读量:2

向后端发起GET请求成功了,POST请求却发生了403,然而再尝试Postman发送POST请求却能成功,为什么?记录一下整体过程

问题与结论

今天和后端联调,发现了一个问题,发起的get请求没有问题,post请求都被拦截了,403forbidden,后端觉得是前端配置问题,于是用 postman发送了请求,并且成功了,这是为什么呢?
403错误
403错误

先说结论确定了前端的配置没有问题后,查看了后端代码与历史修改记录(曾经是没问题的),发现后端修改了一行代码导致的,config.addAllowedOrigin("*"),据后端所说,他们是重写了cors的拦截策略,因为安全性,所以删除了这行代码。

问题结论:没有允许非同origin下的请求

但是该行代码,同时引起了我的思考,为什么postman可以?为什么同样的GET请求可以,但是POST请求不可以?

解决过程

首先,判断并非是前端跨域问题。

在Webpack中设置反向代理通常是为了解决开发环境中的跨域请求问题。可以使用webpack-dev-server的反向代理功能来实现。且前端若配置失败,浏览器返回的错误是这样的。

浏览器跨域
于是应该是后端做了什么相关的策略。后端当时使用postman,发现并无问题。
因为之前项目是没问题的,所以去查了修改记录,所以发现是为了安全考虑,少了那一行代码。

贴上修改后的代码

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 CorsConfig {     @Bean     public CorsFilter corsFilter(){           //1.添加CORS配置信息         CorsConfiguration config = new CorsConfiguration();         //1) 允许的域,不要写*,否则cookie就无法使用了         // config.addAllowedOrigin("*"); //这里填写请求的前端服务器         config.addAllowedOriginPattern("*");         //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);       } } 

为什么GET请求可以?

首先理解,请求头中的origin是什么?

HTTP 协议中的 Origin Header 存在于请求中用于指明当前请求来自于哪个站点

经查询资料, OriginReferer头的升级版, 常用于CORS或者非GETHEAD请求(MDN 的说法有误,不是只有 POST)相关的服务端身份检验

浏览器端Origin无法手动设置

  • Origin头是浏览器保护字段,类似的有 RefererHostContent-LengthKeep-alive等,但是可以通过 nginx 代理修改。浏览器根据约定自动附加

浏览器附加Origin头的规则

  • 根据fetch说明, 只有当请求为跨域请求或者非get,head请求时都会自动附加。不可被编程,不可被编辑。get,head请求由于兼容性,故无法实现

非 CORS 情况下, Origin字段框架使用情况

  • 据我了解, 绝大部分框架都没有使用 Origin 字段, 我所待的几个公司也从未根据此值来判断

所有符合规则的资源都会包含 Origin 头?

  • 不是。例如跨域图片不会包含 Origin 头, 更多资源请查看

比如有的浏览器(IE)能够请求成功,而有的浏览器却请求失败(Chrome)。这不是因为前一个浏览器行为正确,而是因为前一个浏览器发出请求时没有带上 Origin 而后一个浏览器带上了正确的 Origin

而在服务器端,因为没有 Origin Header,所以认为这不是一次 CORS 请求,所以没有进行 CORS 校验。这也反过来要求服务端强制请求带上 Origin Header,才能进一步保证服务器的安全性。

可能当前项目后端请求中,并未校验GET(简单请求)的origin吧?因为本人只是一名前端,个人思考结果。如果有人知道具体原因,还请告知。

为什么Postman请求可以?

首先理解下同源策略

同源策略是浏览器的一个安全机制,限制了一个源(域名、协议、端口)的文档或脚本如何与来自另一个源的资源进行交互。这种限制是为了防止潜在的安全漏洞,比如跨站脚本(XSS)攻击。

但是,Postman 并不是一个浏览器,它是一个独立的工具,不受同源策略的限制。当你在 Postman 中发送请求时,它实际上是在模拟一个 HTTP 请求,并不像浏览器一样执行 JavaScript 代码。因此,Postman 可以轻松地发送请求到不同域名的服务器,并获得响应,而不会受到同源策略的约束。

而且Postman的默认请求头中,并没有Origin的参数。
在这里插入图片描述

理论上来说,如果我手动添加,非同源,是否也会失败,事实证明,的确如此。
在这里插入图片描述

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!