Please help test a CORS issue in Firefox jQuery ajax when 401

后端 未结 4 1620
野的像风
野的像风 2021-01-03 01:10

this is driving me nutters.

jQuery 1.4.2, windows XP sp3

Here is my test.

Load firefox 3.5+

http://plungjan.name/test/testcors.html

w

相关标签:
4条回答
  • 2021-01-03 01:57

    CORS with file://

    If you have problems by allowing origins from the file:// protocol, according to The Web Origin Concept it should be done the same way as any other origins. I could not find information about the browser support, but I think every browser which is supporting CORS does support this one either.

    The Web Origin Concept tells us the following about the file URI scheme:

       4.  If uri-scheme is "file", the implementation MAY return an
           implementation-defined value.
    
              NOTE: Historically, user agents have granted content from the
              file scheme a tremendous amount of privilege.  However,
              granting all local files such wide privileges can lead to
              privilege escalation attacks.  Some user agents have had
              success granting local files directory-based privileges, but
              this approach has not been widely adopted.  Other user agents
              use globally unique identifiers for each file URI, which is
              the most secure option.
    

    According to wikipedia the domain by the file URI scheme is localhost. It is omittable by the address bar, but I don't think it is omittable in the allow origin headers. So if your browser implementation allows origin with a file URI scheme, then you should add file://localhost to your allowed origins, and everything should work properly after that.

    This was how it should work, now meet reality:

    • I tested with current firefox 29.0.1, and it did not work. However the file:// protocol is transformed into null origin by this implementation. So by firefox the null works. I tried with a wider domain list, but I did not manage to allow multiple domains. It seems like firefox does not support a list with multiple domains currently.
    • I tested with chrome 35.0.1916, it works the same way as firefox did.
    • I tested with msie 11.0.9600. By request from the file protocol it always shows an allow blocked content button, even by not allowing the null origin. By other domains it works the same way as the previous browsers.

    HTTP basic auth:

    The credentials part I tried out with PHP and HTTP basic auth.

    http://test.loc
    Displays :-) when logged in and :-( when unauthorized.

    <?php
    
    function authorized()
    {
        if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW']))
            return false;
        return ($_SERVER['PHP_AUTH_USER'] == 'username' && $_SERVER['PHP_AUTH_PW'] == 'password');
    }
    
    function unauthorized()
    {
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: Basic realm="Restricted Area"');
        echo '<a href="http://test.loc">:-(</a>';
    }
    
    if (!isset($_GET['logout']) && authorized()) {
        echo '<a href="http://test.loc?logout=1">:-)</a>';
    } else
        unauthorized();
    

    So this code changes the location by login and logout.

    Cross domain CORS with HTTP basic auth

    http://todo.loc
    Gets the content of http://test.loc with cross domain XHR and displays it.

    cross domain ajax<br />
    <script>
        var xhr = new XMLHttpRequest();
        xhr.open('GET', "http://test.loc", true);
        xhr.withCredentials = true;
        xhr.onreadystatechange = function (){
            if (xhr.readyState==4) {
                document.body.innerHTML += xhr.responseText;
            }
        };
        xhr.send();
    </script>
    

    Requires headers by http://test.loc:

    Access-Control-Allow-Origin: http://todo.loc
    Access-Control-Allow-Credentials: true
    

    Cross scheme CORS with HTTP basic auth

    file:///path/x.html
    Gets the content of http://test.loc with cross scheme XHR and displays it.

    cross scheme ajax<br />
    <script>
        var xhr = new XMLHttpRequest();
        xhr.open('GET', "http://test.loc", true);
        xhr.withCredentials = true;
        xhr.onreadystatechange = function (){
            if (xhr.readyState==4) {
                document.body.innerHTML += xhr.responseText;
            }
        };
        xhr.send();
    </script>
    

    Requires headers by http://test.loc:

    Access-Control-Allow-Origin: null
    Access-Control-Allow-Credentials: true
    

    Conclusion:

    I tested cross-sheme CORS with credentials called from file:// and it works pretty well in firefox, chrome and msie.

    0 讨论(0)
  • 2021-01-03 02:00

    So you need to set an ajax prefilter in your model/collection in order to use CORS. Otherwise it doesn't send the cookie.

    $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
        options.xhrFields = {
          withCredentials: true
        };
    });
    

    I put this in my Model/Collection initialize function.

    0 讨论(0)
  • 2021-01-03 02:07

    This is a stab in the dark since I don't fully understand your problem, but I think you might be having a problem with file: URLs, which are not treated as having any origin. I'm not sure it's even possible to authorize CORS from a file URL.

    0 讨论(0)
  • 2021-01-03 02:13

    These are the conditions to be met to make CORS working with secured services:

    • Service response should contain header Access-Control-Allow-Credentials: true (see Requests with credentials and Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true).
    • Service response header Access-Control-Allow-Origin should not be *. The idea is to return the value passed by client in header Origin (see examples in this post).
    • According to specification, OPTIONS method should return HTTP code 200, thus it cannot be secured (see The CORS).
    • For methods PUT/POST that need to pass certain request headers to service (like Content-Type or Accept), these headers need to be listed in Access-Control-Allow-Headers (see jQuery AJAX fails to work when headers are specified)
    • JavaScript should set this XMLHttpRequest property: xhr.withCredentials = true; (as answered by Kirby)

    Altogether configuration for Apache:

    # Static content:
    SetEnvIf      Request_URI     ".*"                            no-jk
    # RESTful service:
    SetEnvIf      Request_URI     "^/backend/"                    !no-jk
    SetEnvIf      Request_Method  "OPTIONS"                       no-jk
    # Fallback value:
    SetEnv        http_origin     "*"
    SetEnvIf      Origin          "^https?://(localhost|.*\.myconpany\.org)(:[0-9]+)?$" http_origin=$0
    
    Header        set Access-Control-Allow-Credentials    "true"
    Header        set Access-Control-Allow-Origin         "%{http_origin}e"
    Header        set Access-Control-Allow-Methods        "GET,POST,PUT,DELETE"
    Header        set Access-Control-Allow-Headers        "Content-Type, Accept"
    
    JkMount /* loadbalancer
    
    0 讨论(0)
提交回复
热议问题