为什么我的对oauth服务器的获取请求被cors阻止

I spent a decent amount of time trying to get OAuth working for a writing application that integrates Google Drive API. I ran into a bunch of problems with CORS and decided to do some research about what exactly CORS is. I also learned a lot about how to properly make a request to an OAuth server from a browser. If you’ve been struggling with CORS and OAuth 2.0, you might find some of this stuff helpful.

我花了很多时间试图让OAuth在集成了Google Drive API的书写应用程序上工作。 我遇到了许多有关CORS的问题,并决定对CORS的确切含义进行一些研究。 我还学到了很多有关如何正确地从浏览器向OAuth服务器发出请求的知识。 如果您一直在努力使用CORS和OAuth 2.0,那么您可能会发现其中一些有用的东西。

同源政策 (Same Origin Policy)

Really quick, before we go into why we need CORS, we need to know about the Same Origin Policy.

很快,在我们为什么需要CORS之前,我们需要了解相同起源政策。

ALL requests made by the browser are made using the Same Origin Policy, (except for a few methods that we’ll cover later).

浏览器发出的所有请求都是使用Same Origin Policy发出的(除了一些稍后将介绍的方法)。

This means that code executed from one origin CANNOT access content from a different origin. A code’s origin is defined by (PROTOCOL, DOMAIN, and PORT).

这意味着从一个来源执行的代码无法访问来自另一个来源的内容。 代码的原点由(PROTOCOL,DOMAIN和PORT)定义。

Another example of a “cross” origin request:

“交叉”原始请求的另一个示例:

Say you are on a React application hosted at http://localhost:3000 and you try to use fetch to access content from your API at http://localhost:4000 . This request will be denied by the SOP that is enforced by web browsers. (If you have developed full-stack applications, you’ve probably used CORS (Cross-Origin Resource Sharing) to enable cross-origin access. CORS is a way to “loosen” the SOP enforced by browsers and allow cross-origin resource sharing as its name suggests. We’ll get to CORS in a bit.)

假设您使用的是位于http:// localhost:3000上的React应用程序,并且尝试使用fetchhttp:// localhost:4000的API访问内容。 Web浏览器强制执行的SOP将拒绝此请求。 (如果您已经开发了全栈应用程序,则可能已经使用CORS(跨源资源共享)来启用跨域访问。CORS是一种“松开”由浏览器实施的SOP并允许跨域资源共享的方法。顾名思义,稍后我们会介绍CORS。)

为什么浏览器强制执行SOP? (Why do browsers enforce SOP?)

For security reasons.

出于安全原因。

Here is an answer from stackexchange that shows how the same origin policy protects users.

这是来自stackexchange的答案,显示了相同的原始策略如何保护用户。

“Why is the same origin policy important?

“为什么同一个原籍政策很重要?

Assume you are logged into Facebook and visit a malicious website in another browser tab. Without the same origin policy, JavaScript on that website could do anything to your Facebook account that you are allowed to do. For example read private messages, post status updates, analyze the HTML DOM-tree after you entered your password before submitting the form.

假设您已登录Facebook,并在另一个浏览器选项卡中访问了恶意网站。 没有相同的原始策略,该网站上JavaScript可能会对您的Facebook帐户执行允许的任何操作。 例如,在输入密码后提交表单之前,阅读私人消息,发布状态更新,分析HTML DOM树。

But of course, Facebook wants to use JavaScript to enhance the user experience. So it is important that the browser can detect that this JavaScript is trusted to access Facebook resources. That’s where the same origin policy comes into play: If the JavaScript is included from a HTML page on facebook.com, it may access facebook.com resources.

但是,当然,Facebook希望使用JavaScript来增强用户体验。 因此,重要的是浏览器可以检测到该JavaScript受信任以访问Facebook资源。 这就是相同的原始策略起作用的地方:如果JavaScript来自facebook.com上HTML页面,则它可以访问facebook.com资源。

Now replace Facebook with your online banking website, and it will be obvious that this is an issue.”

现在,用您的在线银行网站替换Facebook,这显然是一个问题。”

By ensuring that requests can only be made to the SAME origin the request originated from, browsers are able to keep user information secure from malicious websites.

通过确保仅对发出请求的源是同一请求,浏览器就能够保护用户信息免受恶意网站的侵害。

CORS(跨源资源共享) (CORS (Cross Origin Resource Sharing))

CORS allows us to loosen up the SOP enforced by browsers. All CORS is a process by which we can safely allow resource sharing between two different origins. It works by specifying extra HTTP headers in both the response and the request. Using these “CORS headers”, the browser decides whether an origin should have access to the requested content.

CORS允许我们放宽浏览器强制执行的SOP。 所有CORS是一个过程,通过它我们可以安全地允许两个不同来源之间共享资源。 它通过在响应和请求中指定额外的HTTP标头来工作浏览器使用这些“ CORS标头”来确定源是否应有权访问所请求的内容

配置CORS (Configuring CORS)

First, the content server needs to configure CORS and specify which Origins should be able to access content from the content server — you can also configure CORS to only allow certain things like Methods (i.e. GET, POST, DELETE) or Headers (i.e. Content-Type); specifying * for Access-Control-Allow-Origins will allow requests from all origins. Check out the documentation for how to configure CORS for your back end servers.

首先,内容服务器需要配置CORS并指定哪些Origins应该能够从内容服务器访问内容-您还可以将CORS配置为仅允许某些方法(例如方法(即GET,POST,DELETE)或标头(即内容) -类型); 为Access-Control-Allow-Origins指定*将允许来自所有来源的请求。 查看文档,了解如何为后端服务器配置CORS。

Then, the requester sends an HTTP request to the server with the HTTP header Origin, and the HTTP request mode set to cors (see Sec-Fetch-Mode below).

然后,请求者将HTTP请求发送到带有HTTP标头Origin的服务器,并且HTTP请求模式设置为cors (请参阅下面的Sec-Fetch-Mode )。

The server is going to receive the request and return a response with the CORS (e.g. Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers) configuration in the Headers.

服务器将接收请求,并使用Access-Control-Allow-Headers的CORS配置(例如Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers )配置返回响应。

It looks like this.

看起来像这样。

Image for post

This is the code used to generate that request.

这是用于生成该请求的代码。

Once the browser gets the response back from the content server, it compares the CORS headers in the response and the request. If the origin is included in Access-Control-Allow-Origin and all other Access-Control-Allow… configurations are met, the browser will allow the content to be served. If not, the request is blocked by the CORS policy.

浏览器从内容服务器获得响应后,便会比较响应和请求中的CORS标头。 如果源包含在Access-Control-Allow-Origin并且满足所有其他Access-Control-Allow…配置,则浏览器将允许提供内容。 如果不是,则该请求被CORS策略阻止。

An important distinction to make here is that the browser is enforcing the CORS policy, NOT the content server. The requesting server as well as the content server are only including extra CORS headers into the HTTP request and response respectively. The browser receives the response and determines whether the CORS headers are satisfactory, and thereby, whether the content should be served.

这里要做出的重要区别是浏览器正在执行CORS策略,而不是内容服务器。 请求服务器和内容服务器仅在HTTP请求和响应中分别包含额外的CORS标头。 浏览器接收响应并确定CORS标头是否令人满意,从而确定是否应提供内容。

我们如何访问不受OAuth服务器控制的服务器上的内容? (How can we access content on Servers we don’t have control over for example OAuth servers?)

Configuring CORS is an easy way to allow different origins access to the server content, but we can only configure CORS for servers we control.

配置CORS是一种允许不同来源访问服务器内容的简便方法,但是我们只能为我们控制的服务器配置CORS。

If we want to use any third-party APIs, we most likely need to receive an access_token from the OAuth server, and the OAuth server won’t have CORS configured to allow our application’s origin access.

如果我们想使用任何第三方API,则很可能需要从OAuth服务器接收一个access_token ,并且OAuth服务器将没有配置CORS来允许我们的应用程序进行原始访问。

Side Note: (I really recommend if you have any confusion on how OAuth 2.0 works to check out this Medium post that explains OAuth 2.0 very simply).

旁注:(如果您对OAuth 2.0的工作方式有任何疑问,我强烈建议您查看这篇非常简单地解释OAuth 2.0的中级文章)。

Using any sort of fetch API from a browser to an OAuth server will give you this error.

从浏览器到OAuth服务器使用任何类型的提取API,都会出现此错误。

使用<form>提交跨源请求到OAuth Server (Using <form> to submit cross origin request to OAuth Server)

In the beginning, we said that almost all requests made by the browser are made using the same origin policy. Some requests that don’t enforce the same origin policy include requests made by the tags <script> <img> <forms> <a> <frame> , and <iframe> .

在一开始,我们说过浏览器发出的几乎所有请求都是使用相同的原始策略发出的。 某些不执行相同原始策略的请求包括标记<script> <img> <forms> <a> <frame><iframe>发出的请求。

Since OAuth servers return the authorization code as a parameter in a redirect URL, we can use a tag like form to make a Cross origin request to the OAuth server. (Forms have no way of accessing an HTTP response, but a successful request to an OAuth server will simply redirect with the “response” in the URL, so forms are perfect to use).

由于OAuth服务器在重定向URL中将授权代码作为参数返回,因此我们可以使用诸如form类的标签向OAuth服务器发出跨源请求。 (表单无法访问HTTP响应,但是对OAuth服务器的成功请求将仅使用URL中的“响应”进行重定向,因此表单非常适合使用)。

After the OAuth request is authorized by the server and the user, it will redirect to this URL (the URL that I specified the Oauth server to redirect to; you need to configure this in the Oauth credentials for the API you’re using),

服务器和用户授权OAuth请求后,它将重定向到该URL(我指定要重定向到的Oauth服务器的URL;您需要在Oauth凭据中为正在使用的API进行配置),

http://localhost:3000/client#state=oauth&access_token=myaccesstoken&token_type=Bearer&expires_in=3599&scope=https://www.googleapis.com/auth/drive

http://localhost:3000/client#state=oauth&access_token=myaccesstoken&token_type=Bearer&expires_in=3599&scope=https://www.googleapis.com/auth/drive

In React, we can easily parse the URL using qs package, and using history from react-router-dom .

在React中,我们可以轻松地使用qs包以及来自react-router-dom history来解析URL。

Now that we have our access token we can make requests to the google drive API!

现在我们有了访问令牌,我们可以向Google Drive API发出请求了!

这篇文章值得一提的是: (Things to take away from this post:)

  1. BROWSERS use the same origin policy so that Javascript from one origin can’t access content from another origin.

    浏览器使用相同的来源策略,因此来自一个来源的Javascript无法访问来自另一个来源的内容。
  2. CORS is simply a mechanism of allowing “cross-origin” access. CORS works by both the requester and the responder providing extra “CORS headers”. The BROWSER will look at the CORS headers of the request/response and determine if the content should be served.

    CORS只是允许“跨域”访问的机制。 CORS由请求者和响应者共同提供额外的“ CORS标头”。 浏览器将查看请求/响应的CORS标头,并确定是否应提供内容。
  3. Tags like <form> <script> <img> and others DON’T use SOP. We can easily use a <form> tag to submit a request to an OAuth server and capture the response in the URL.

    诸如<form> <script> <img>类的标签不使用SOP。 我们可以轻松地使用<form>标记向OAuth服务器提交请求,并在URL中捕获响应。

I hope some of this material made working with CORS and configuring your Oauth 2.0 a little bit easier. Good luck coding!

我希望其中一些资料可以使CORS能够更轻松地配置Oauth 2.0。 祝您好运!

资源和进一步阅读: (Resources and further readings:)

翻译自: https://medium.com/dev-genius/why-is-my-fetch-request-to-oauth-server-being-blocked-by-cors-c8bdadb92b30

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值