【问题标题】:POST request does not work from Angular5 code but works from Postman [duplicate]POST 请求不适用于 Angular5 代码,但适用于 Postman [重复]
【发布时间】:2018-08-27 21:34:21
【问题描述】:

前端:Angular5

后端:Java(在 Wildfly 8.x 服务器上运行)

在从我的 Angular 应用程序向服务器发出带有 content-type: 'application/json' 的 HTTP POST 请求时,我收到以下错误:

无法加载http://localhost:8080/myk/api/v1/events/addevent: 对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 使用权。响应的 HTTP 状态代码为 403。

这是请求的代码:

const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; this.http.post("http://localhost:8080/myk/api/v1/events/addevent", jsonPayload, httpOptions).subscribe();

在检查时,我发现不是POST 请求,而是一个OPTIONS 请求(根据this MDN article on CORS and preflighted requests)。

但是,当我使用 Postman 尝试相同的请求时,它工作得非常好。

当我不在服务器上处理 OPTIONS 请求时,Postman 如何不会遇到 OPTIONS 请求的问题?

另外,我能做些什么(同时保持相同的content-type 并且无需修改服务器端代码)来解决这个问题?

注意 1: 尽管this question 解决了相同的问题,但建议的解决方案需要更改内容类型。

注意 2: 当我运行另一个尝试使用 ajax 调用发出 POST 请求的应用程序(不是由我在 Angularjs 中设计的)时,它工作正常。 (我不明白为什么会这样,此外,如果能提供与 angular5 相关的答案,我将不胜感激。我附上了这个注释,以防它有助于找出 Angular5 应用程序的问题)

编辑:这可能有点挑剔,但我特别希望尝试通过修改客户端代码而不是使用扩展或与浏览器相关的任何修改来解决上述问题。但是,如果这些都不可能,我愿意更改服务器端代码。

【问题讨论】:

  • 如果您不传递标头,您将不会收到 OPTIONS 调用
  • 在这种情况下,我如何指定要发送的数据是 JSON?此外,在 Postman 中,我包含了一个标头,指示内容类型为 application/json(同时选择原始数据作为正文类型),它仍然有效
  • 无论如何,您最好接受后端代码中的标头,这只是一行代码。不照顾 CORE 就无法逃脱
  • @RequestMapping(value="/addevent",method=RequestMethod.POST,produces=org.springframework.http.MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> addNewEvent( @RequestBody EventDTO event,HttpServletRequest request) 这是我当前服务器端代码的方法签名。 Postman 如何仍然能够成功访问它并将 JSON 数据传递到服务器?
  • “但是,如果这一切都不可能,我愿意更改服务器端代码。” — 您需要修改服务器端代码。如果您的客户端可以禁用旨在阻止您的客户端代码访问其他网站的安全功能,那将是愚蠢的。

标签: angular cors http-post postman


【解决方案1】:

此问题称为 CORSCross Origin Resource Sharing。当请求和响应的来源不同时,就会出现这种情况。例如:如果您的项目在 https://139.43.33.122:1111/ 上,而您的服务器托管在 https://123.0.3.444:3000 上,那么您的请求和响应的来源完全不同,因此,浏览器将阻止响应。这是浏览器的事情。邮递员不关心他们的出身。要接收响应,有两种方法(可能更多,但我只使用这两种)。

  1. 附加标头:如果您有权访问/许可服务器代码,则在服务器响应中添加附加标头: Access-Control-Allow-Origin:http://siteA.com,Access-Control-Allow-Methods:GET、POST、PUT、Access-Control-Allow-Headers:Content-Type

  2. 使用扩展程序:有多个扩展程序可以绕过此限制。如果您无权更改服务器响应,那么这是可行的方法。我个人仅使用此方法。

【讨论】:

  • "Access-Control-Allow-Origin: *" — 这是一个预检请求。这还不够。
  • “使用扩展”——这是在开发期间使用的 hack,在生产期间完全不切实际。
  • 谢谢。我之前曾尝试使用 Chrome 的 CORS 扩展,但似乎没有什么不同。安装并打开扩展程序后没有什么可做的,对吧(据我所见,它的唯一功能似乎是打开和关闭它)?
  • @Quentin 同意扩展。我应该在我的问题中提到这一点
  • @Quentin 感谢提醒,我差点忘了访问控制部分,是的,扩展是一个开发黑客。
【解决方案2】:

由于article,我找到了避免 CORS 和 403 错误的技巧。

  1. 在您的 Google Chrome 上添加 Postman 拦截器:https://chrome.google.com/webstore/detail/postman-interceptor/aicmkgpgakddgnaphhhpliifpcfhicfo/support?hl=en

  2. 在 Postman 中激活 Postman 拦截器

  1. 借助 Postman 界面启动您的请求并捕获 cookie

  1. 打开您的 Chrome 开发工具,进入控制台并手动添加通过 postman 拦截器找到的 cookie

    document.cookie="keyofcookie=valueofcookie"

重试您的请求,它有效!

否则,为了避免 CORS,您可以使用 here 描述的代理。

【讨论】:

  • 谢谢,但这不是每个用户必须单独进行的浏览器修复吗?
  • 不幸的是,你是对的。这是一个非常肮脏的解决方案。但是,您可以自定义 cookie,使其成为永恒的 [developer.mozilla.org/fr/docs/Web/API/Document/cookie],并在每个用户会话开始时推送它。这是我找到的唯一解决方案。
  • 大声笑,你需要告诉你的所有用户在他们的浏览器上安装拦截器 LOLOLOOLOLOLOLOL
猜你喜欢
  • 2022-01-21
  • 2017-08-06
  • 1970-01-01
  • 2020-06-17
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 2015-09-19
相关资源
最近更新 更多