使用 jQuery 和 Ajax 进行基本身份验证

Posted

技术标签:

【中文标题】使用 jQuery 和 Ajax 进行基本身份验证【英文标题】:Use basic authentication with jQuery and Ajax 【发布时间】:2011-07-27 07:21:41 【问题描述】:

我正在尝试通过浏览器创建基本身份验证,但我无法真正实现。

如果此脚本不在这里,浏览器身份验证将接管,但我想告诉浏览器用户即将进行身份验证。

地址应该是这样的:

http://username:password@server.in.local/

我有一个表格:

<form name="cookieform" id="login" method="post">
      <input type="text" name="username" id="username" class="text"/>
      <input type="password" name="password" id="password" class="text"/>
      <input type="submit" name="sub" value="Submit" class="page"/>
</form>

还有一个脚本:

var username = $("input#username").val();
var password = $("input#password").val();

function make_base_auth(user, password) 
  var tok = user + ':' + password;
  var hash = Base64.encode(tok);
  return "Basic " + hash;

$.ajax
  (
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '"username": "' + username + '", "password" : "' + password + '"',
    success: function ()
    alert('Thanks for your comment!');
    
);

【问题讨论】:

所以您希望浏览器处理 BASIC 身份验证?为什么不只使用基于表单的身份验证? @no.good.at.coding 如果您需要在身份验证之后与第三方 API 集成(这是我正在尝试做的 - developer.zendesk.com/rest_api/docs/core/…) 【参考方案1】:

让我告诉你和 Apache 替代方案 - 在开始真正的 JQuery Ajax 身份验证之前需要它的 IIS

例如,如果我们有 /secure/* 路径。我们需要创建 web.config 并禁止访问。只有在发送之前应用后必须能够访问 /secure 路径中的页面

<?xml version="1.0"?>
<configuration>
  <system.web>
    <!-- Anonymous users are denied access to this folder (and its subfolders) -->
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
</configuration>



<security>
   <authentication>
      <anonymousAuthentication enabled="false" />
      <basicAuthentication enabled="true" />
   </authentication>
</security>

【讨论】:

【参考方案2】:

一年的变化。除了代替 xhr.setRequestHeader 的 header 属性之外,当前的 jQuery (1.7.2+) 还包括一个带有 $.ajax 调用的用户名和密码属性。

$.ajax
(
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  username: username,
  password: password,
  data: ' "comment" ',
  success: function ()
    alert('Thanks for your comment!'); 
  
);

从 cmets 和其他答案编辑:要清楚 - 为了在没有 401 Unauthorized 响应的情况下抢先发送身份验证,而不是 setRequestHeader(-1.7 之前)使用 'headers'

$.ajax
(
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  headers: 
    "Authorization": "Basic " + btoa(USERNAME + ":" + PASSWORD)
  ,
  data: ' "comment" ',
  success: function ()
    alert('Thanks for your comment!'); 
  
);

【讨论】:

不应该是username而不是user吗?它也不完全相同:从在线文档和我的经验来看,它看起来不像某些 API 所要求的那样抢先。换句话说,它仅在返回代码 401 时才发送 Authorization 标头。 @StefanoFratini - 你在这两个方面都是正确的。修复了用户名字段,很高兴了解抢先式身份验证与仅在质询时响应。像其他答案一样明确设置标题将允许使用基本身份验证的这种“被动”变体。 对我来说,上面的选项不起作用,这就像一个魅力......谢谢 见上面的评论,请更正这个答案以表明 "Authorization": "Basic " + btoa("user:pass") 作为正确的标题 这就是我一直在寻找的答案!对我来说,这个答案的关键是如何使用“标头”来抢先发送身份验证。我的问题在这里得到了回答。 ***.com/questions/28404452/…【参考方案3】:

根据 SharkAlley 的回答,它也适用于 nginx

我正在寻找一种解决方案,通过 jQuery 从 nginx 后面的服务器获取数据并受 Base Auth 限制。这对我有用:

server 
    server_name example.com;

    location / 
        if ($request_method = OPTIONS ) 
            add_header Access-Control-Allow-Origin "*";
            add_header Access-Control-Allow-Methods "GET, OPTIONS";
            add_header Access-Control-Allow-Headers "Authorization";

            # Not necessary
            #            add_header Access-Control-Allow-Credentials "true";
            #            add_header Content-Length 0;
            #            add_header Content-Type text/plain;

            return 200;
        

        auth_basic "Restricted";
        auth_basic_user_file /var/.htpasswd;

        proxy_pass http://127.0.0.1:8100;
    

javascript 代码是:

var auth = btoa('username:password');
$.ajax(
    type: 'GET',
    url: 'http://example.com',
    headers: 
        "Authorization": "Basic " + auth
    ,
    success : function(data) 
    ,
);

我觉得有用的文章:

    本主题的答案 http://enable-cors.org/server_nginx.html http://blog.rogeriopvl.com/archives/nginx-and-the-http-options-method/

【讨论】:

【参考方案4】:

按照其他人的建议,可以直接在Ajax调用中设置用户名和密码:

$.ajax(
  username: username,
  password: password,
  // ... other parameters.
);

如果您不想以纯文本形式存储凭据,请使用 headers 属性:

$.ajax(
  headers: "Authorization": "Basic xxxx",
  // ... other parameters.
);

无论您以哪种方式发送,服务器都必须非常有礼貌。对于 Apache,您的 .htaccess 文件应如下所示:

<LimitExcept OPTIONS>
    AuthUserFile /path/to/.htpasswd
    AuthType Basic
    AuthName "Whatever"
    Require valid-user
</LimitExcept>

Header always set Access-Control-Allow-Headers Authorization
Header always set Access-Control-Allow-Credentials true

SetEnvIf Origin "^(.*?)$" origin_is=$0
Header always set Access-Control-Allow-Origin %origin_ise env=origin_is

说明:

对于某些跨域请求,浏览器会发送一个预检 OPTIONS 请求,该请求缺少您的身份验证标头。将您的身份验证指令包装在 LimitExcept 标记内,以正确响应预检。

然后发送一些headers告诉浏览器允许进行身份验证,Access-Control-Allow-Origin来授予跨站请求的权限。

在某些情况下,* 通配符不起作用作为 Access-Control-Allow-Origin 的值:您需要返回被调用者的确切域。使用 SetEnvIf 捕获此值。

【讨论】:

感谢浏览器发送不带身份验证标头的 CORS 预检请求的信息!像这样的细节可能会导致数小时的调试!【参考方案5】:

上面的例子有点混乱,这可能是最好的方法:

$.ajaxSetup(
  headers: 
    'Authorization': "Basic " + btoa(USERNAME + ":" + PASSWORD)
  
);

我从 Rico 和 Yossi 的回答中得到了上述内容。

btoa 函数 Base64 对字符串进行编码。

【讨论】:

这是个坏主意,因为您将使用 all AJAX 请求发送登录信息,而不管 URL 是什么。此外,$.ajaxSetup() 的文档说“为未来的 Ajax 请求设置默认值。不建议使用它。【参考方案6】:

JSONP 不适用于基本身份验证,因此 jQuery beforeSend 回调不适用于 JSONP/Script。

我设法通过在请求中添加用户和密码来解决这个限制(例如 user:pw@domain.tld)。这适用于几乎所有不支持通过 URL 进行身份验证的浏览器除了 Internet Explorer(根本不会执行调用)。

见http://support.microsoft.com/kb/834489。

【讨论】:

猜测从安全角度来看,不允许这样做是明智的选择 链接已损坏 (404)。【参考方案7】:

有3种方法可以实现,如下所示

方法一:

var uName="abc";
var passwrd="pqr";

$.ajax(
    type: 'GET/POST',
    url: 'urlpath',
    headers: 
        "Authorization": "Basic " + btoa(uName+":"+passwrd);
    ,
    success : function(data) 
      //Success block  
    ,
   error: function (xhr,ajaxOptions,throwError)
    //Error block 
  ,
);

方法二:

var uName="abc";
var passwrd="pqr";

$.ajax(
    type: 'GET/POST',
    url: 'urlpath',
     beforeSend: function (xhr) 
        xhr.setRequestHeader('Authorization', "Basic " + btoa(uName+":"+passwrd)); 
    ,
    success : function(data) 
      //Success block 
   ,
   error: function (xhr,ajaxOptions,throwError)
    //Error block 
  ,
);

方法三:

var uName="abc";
var passwrd="pqr";

$.ajax(
    type: 'GET/POST',
    url: 'urlpath',
    username:uName,
    password:passwrd, 
    success : function(data) 
    //Success block  
   ,
    error: function (xhr,ajaxOptions,throwError)
    //Error block 
  ,
);

【讨论】:

嗨,我已经测试了所有 3 种方法。但它从未产生 Authorization 标头。作为 dataType 我需要使用 jsonp 因为做跨域调用。并调用我没有机会更改的应用程序 API。直接从java http客户端它可以工作。但我无法通过 jquery 处理它。【参考方案8】:

使用 jQuery 的 beforeSend 回调添加带有身份验证信息的 HTTP 标头:

beforeSend: function (xhr) 
    xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
,

【讨论】:

我正在使用你提供的示例,但它不起作用` $.ajax ( url: "server.in.local/index.php", beforeSend: function (xhr) xhr.setRequestHeader("Authorization", “基本”+encodeBase64(“用户名:密码”));,成功:function(val)//alert(val);alert(“感谢您的评论!”);); ` beforeSend: function(xhr) xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); ; 为我工作 问题...如果我通过的凭据失败,则在 Chrome 中,用户会看到一个对话框以再次输入用户名/密码。如果凭据失败,如何防止出现第二个对话框? 这不会将用户名和密码公开给任何人看吗?即使它在base64中,他们也可以对其进行解码。与下面的答案相同。 @calebB 基本身份验证通常只是将用户名和密码公开,任何人都可以看到。这不仅仅是这里描述的方法的问题。如果正在使用基本身份验证或真正的任何身份验证,则还应使用 SSL。【参考方案9】:

使用jQuery ajaxSetup函数,可以为所有ajax请求设置默认值。

$.ajaxSetup(
  headers: 
    'Authorization': "Basic XXXXX"
  
);

【讨论】:

【参考方案10】:

或者,直接使用 1.5 中引入的 headers 属性:

headers: "Authorization": "Basic xxxx"

参考:jQuery Ajax API

【讨论】:

【参考方案11】:

使用beforeSend callback 添加带有身份验证信息的 HTTP 标头,如下所示:

var username = $("input#username").val();
var password = $("input#password").val();  

function make_base_auth(user, password) 
  var tok = user + ':' + password;
  var hash = btoa(tok);
  return "Basic " + hash;

$.ajax
  (
    type: "GET",
    url: "index1.php",
    dataType: 'json',
    async: false,
    data: '',
    beforeSend: function (xhr) 
        xhr.setRequestHeader('Authorization', make_base_auth(username, password)); 
    ,
    success: function ()
        alert('Thanks for your comment!'); 
    
);

【讨论】:

以上是关于使用 jQuery 和 Ajax 进行基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 AJAX、JQuery、Apache 和基本身份验证的跨源请求

使用 jQuery/ajax 的基本身份验证

是否可以使用 jQuery 加密 AJAX 调用以进行身份​​验证?

使用带有摘要身份验证、jquery ajax 调用的 RestFul PHP Web 服务

jQuery 基本身份验证不起作用

为啥 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同?