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

时间:2012-03-13 20:59:40

标签: javascript jquery ajax basic-authentication http-authentication

我有一个基于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似乎甚至考虑在同一台机器上使用不同的端口号和#34;跨站点"。

3 个答案:

答案 0 :(得分:3)

这个问题可能已经过了它的'到期日期,但是我和Jquery一起工作时遇到了同样的问题。

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

请查看以下请求(简洁起见),首先在JQuery AJAX方法中使用“username”和“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

请注意,第一种方法在请求中不包含“授权”标头,而是在目标网址前加上前缀。我不是HTTP基本身份验证的专家,但它会表明前者不是一个正确的实现,因此失败(或者至少它与我自己的服务器实现有关)。

关于使用JSONP的OPTIONS请求 - 您可以尝试在网址中使用?callback=?而不是使用crossdomain选项,只是为了明确。

答案 1 :(得分:1)

这是一些充当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();

答案 2 :(得分:1)

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

此解决方案与appserver无关,因此也适用于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>

此致 莫里吉奥