【问题标题】:Use basic authentication with jQuery and Ajax使用 jQuery 和 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/…

标签: javascript jquery ajax authentication


【解决方案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") } 作为正确的标题
    • 这就是我一直在寻找的答案!对我来说,这个答案的关键是如何使用“标头”来抢先发送身份验证。我的问题在这里得到了回答。 stackoverflow.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) {
        },
    });
    

    我觉得有用的文章:

    1. 本主题的答案
    2. http://enable-cors.org/server_nginx.html
    3. 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_is}e 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!'); 
              }
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-01-01
            • 2012-01-27
            • 2012-04-30
            • 2015-08-12
            • 2017-06-13
            相关资源
            最近更新 更多