jQuery, CORS, JSON (without padding) and authentication issues

北战南征 提交于 2020-01-11 05:42:11

问题


I have two domains. I'm trying to access a JSON object from one domain through a page on another. I've read everything I could find regarding this issue, and still can't figure this out.

The domain serving the JSON has the following settings:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
Header set Access-Control-Allow-Headers "origin, authorization, accept"

From my other domain, I'm calling the following:

$.ajax({
         type:'get',
         beforeSend: function(xhr) {
             var auth = // authentication; 
             xhr.setRequestHeader("Authorization", "Basic " + auth);
         }
         url:myUrl,
         dataType:'json',
         error: function(xhr, textStatus, errorThrown) { console.log(textStatus, errorThrown); }
      })

I know that 'auth' is initialized properly (logged and checked). However, this does not work. In Firefox's Console, I get Request URL: ...

Request Method:
OPTIONS

Status Code:
HTTP/1.1 401 Authorization Required

If I get rid of the beforeSend:... part, I see the following

Request Method:
GET

Status Code:
HTTP/1.1 401 Authorization Required

However, the domain serving JSON also can serve JSONP. I don't want to use this, mainly because the application will be running constantly on a dedicated browser, and I'm worried about this issue. More importantly, I would really like to know what is actually wrong with what I am doing. I know that for practical purposes there are various ways to overcome the JSONP memory leak (such as not using jQuery).

At any rate, when I did use JSONP, my code looked like this:

$.ajax({
    url:newUrl,
    dataType:'jsonp',
    jsonp:'jsonp'
}).done(function(d){console.log(d)})

This gets the following

Request Method:
GET

Status Code:
HTTP/1.1 200 OK

after it prompts me with an alert box for a username and password.

Is there a fundamental difference in the way jQuery handles JSONP requests as opposed to JSON requests? And if so, how can I fix this?

Thanks.

Edit: Here's what I did find.

Basically, because I need authentication, the GET request is sending an Authorization header. However, this is not a "simple" header, and so the browser is sending a pre-flight request (the OPTIONS). This preflight request doesn't have any authentication, though, and so the server was rejecting it. The "solution" was to set the server to let OPTIONS request not require authentication, and report an HTTP status of 200 to it.

Reference: http://www.kinvey.com/blog/item/61-kinvey-adds-cross-origin-resource-sharing-cors

mail-archive[.com]/c-user@axis.apache.org/msg00790.html (not allowed to post more links)

Unfortunately, the "solution" is only working on Firefox and not Chrome. Chrome simply shows the request in red, but doesn't give me any more info on why it failed.

Edit 2: Fixed on Chrome: The server I was trying to get data from had a security certificate which was not trusted. The preflight request on Chrome failed because of this. Solution superuser[.com]/questions/27268/how-do-i-disable-the-warning-chrome-gives-if-a-security-certificate-is-not-trust (not allowed to post more links)


回答1:


Welp, now that I have enough rep a while later, I might as well answer this question and accept it.

When you attempt to send a GET json request to a server with headers, the browser first sends an OPTION request to make sure that you can access it. Unfortunately, this OPTION request cannot carry with it any authentication. This means that if you want to send a GET with auth, the server must allow an OPTION without auth. Once I did this, things started working.




回答2:


Some examples available here may illustrate further how access control can be combined with CORS. Specifically the credentialed GET example. Access control requires that the request set the withCredentials flag to true on the XMLHttpRequest, and for the server handling the OPTIONS method to do two things:

  1. Set Access-Control-Allow-Credentials: true
  2. Not use a wildcard * in the Access-Control-Allow-Origin header. This has to be set to the origin exactly according to the MDN docs on HTTP access control (CORS).

Essentially, the thing processing the OPTIONS request needs to send back appropriate response headers so you can make that credentialed request.

In your question you stated that the service you are interacting with is returning Access-Control-Allow-Origin: *, which is not compatible with a credentialed cross-domain request. This needs to return the origin specifically.

The aforementioned MDN Http Access Control (CORS) documentation also links to the Server-Side Access Control documentation outlining how a server would potentially respond to various cross domain requests - including handling a cross domain credentialed POST request that requires you to send back the correct headers in response to the OPTIONS method. You can find that example here.




回答3:


Why don't you try typing the URL you are fetching the JSON from into your browser and seeing what happens. It sounds like you literally just need to authenticate into this other website to access it.

If your site needs to work in other browsers like IE, you WILL need JSONP, by the way. The security won't allow the cross site request to work. The headers won't change that. I believe you will also need to add a security policy in your headers.



来源:https://stackoverflow.com/questions/11199426/jquery-cors-json-without-padding-and-authentication-issues

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!