使用HTTP基本身份验证的JQuery Ajax调用

JQuery Ajax calls with HTTP Basic Authentication

本文关键字:JQuery Ajax 调用 身份验证 HTTP 使用      更新时间:2023-09-26

我有一个基于REST的服务器,我正试图使用JQuery与它进行通信。XML和JSON都可以作为响应格式,所以我使用JSON。

连接都是SSL,因此HTTP基本身份验证一直是我们选择的授权方法,我们在其他前端(原始Javascript、Silverlight等)没有遇到任何问题

现在,我正试图将一些东西与JQuery结合起来,并在使用HTTP基本身份验证时遇到了无尽的问题。

我已经仔细研究了以前的许多问题,其中大多数问题的解决方案似乎实际上不起作用,或者将整个问题归咎于跨源访问,我已经在基本的Javascript测试中克服了这一点。响应总是为请求中提供的Origin标头提供Access-Control-Allow-Origin集,这可以在我的测试的响应中看到。

在基本的javascript中,整个调用只需使用即可完成

req.open('GET', 'https://researchdev-vm:8111/card', true, 'test', 'testpassword');

JQuery在这方面的尝试相当标准:

        $.ajax({
        username: 'test',
        password: 'testpassword',
        url: 'https://researchdev-vm:8111/card',
        type: 'GET',
        dataType: 'json',
        crossDomain: true,
        /*data: { username: 'test', password: 'testpassword' },*/
        beforeSend: function(xhr){
            xhr.setRequestHeader("Authorization",
                //"Basic " + encodeBase64(username + ":" + password));
                "Basic AAAAAAAAAAAAAAAAAAA=");
        },
        sucess: function(result) {
            out('done');
        }
    });

似乎唯一能提供身份验证的方法是在beforeSend()函数中直接插入Base64编码的数据。如果不包括这一点,就没有取得任何进展。用户名和密码属性似乎被完全忽略了。

通过提供beforeSend()行为,GET调用得到包含数据的肯定响应。但是,由于这是一个跨站点调用,OPTIONS调用在GET调用之前执行,并且总是失败,因为它没有使用beforeSend(),因此由于身份验证失败而得到401响应。

有没有更好的方法来完成本应是微不足道的任务?OPTIONS请求没有使用beforeSend()函数处理这一事实是否应被视为错误?是否有办法完全禁用OPTIONS检查?不可能使此调用不跨站点,因为Javascript似乎甚至将同一台机器上的不同端口号视为"跨站点"。

这个问题可能已经过了有效期,但我在处理Jquery时遇到了同样的问题。

username和password属性似乎不像通常完成HTTP基本身份验证那样对用户名/密码进行base64编码。

查看以下请求(为简洁起见,请缩短),首先在JQueryAJAX方法中使用"username"answers"password"参数:

Request URL:http://testuser%40omnisoft.com:testuser@localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Host:localhost:60023

现在使用beforeSend方法:

Request URL:http://localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Host:localhost:60023

请注意,第一个方法在请求中不包括"Authorization"标头,而是在目标URL前加前缀。我不是HTTP基本身份验证方面的专家,但这表明前者不是一个正确的实现,因此失败了(或者至少在我自己的服务器实现中失败了)。

至于使用JSONP的OPTIONS请求,您可以尝试在URL中使用?callback=?,而不是使用crossdomain选项,只是为了明确起见。

对于遇到此问题的任何人,我已经解决了使用Apache拦截OPTIONS请求并仅将GET和POST转发到后端的问题。

此解决方案独立于应用程序服务器,因此也适用于PHP和Java:

<VirtualHost *:80>
    # ServerName and other configuration...

    # CORS
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "OPTIONS, GET, PUT, POST" 
    Header set Access-Control-Allow-Headers "Authorization"
    # Intercept OPTIONS calls
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} ^(OPTIONS)$
    RewriteRule .* - [L]
    # Backend, adapt this line to fit your needs
    RewriteRule /(.*) ajp://localhost:8010/$1 [L,P]
</VirtualHost>

谨致问候,Maurizio

这里有一些东西可以作为AJAX调用的直通身份验证。这依赖于NTLM在javascript将从中执行的页面上进行身份验证。也许这会对你有所帮助:

PHP代码:

<?php 
$headers = apache_request_headers();
if (isset($headers['Authorization'])) 
   echo "<script>var auth = " . $headers['Authorization'] . "</script>";
unset($headers);
?>

使用jQuery,您可以这样使用它:

$.ajax({
        type: 'POST',
        url: './somePage.php',
        data: {"test":true},
        dataType: 'json',
        success: function(data) {
            console.log(data.username);
        },
        beforeSend : function(req) {
            req.setRequestHeader('Authorization', auth); // <<<<----- USED HERE
        },
});

对于标准XMLHttpRequest:

var xml = new XMLHttpRequest();
xml.open('GET', './somePage.php', true);
xml.setRequestHeader('Authorization', auth); // <<<<----- USED HERE
xml.send();