对jQuery和Ajax使用基本身份验证


419

我正在尝试通过浏览器创建基本身份验证,但我真的无法到达那里。

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

地址应类似于:

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!');
    }
});

6
因此,您希望浏览器处理BASIC身份验证吗?为什么不只使用基于表单的身份验证?
no.good.at.coding

@ no.good.at.coding如果您需要与落后的认证第三方API集成(这是我想做的事- developer.zendesk.com/rest_api/docs/core/...
布赖恩·汉内

Answers:


466

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

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

6
我使用的是您提供的示例,但是它不起作用`$ .ajax({url:“ server.in.local / index.php ”,beforeSend:function(xhr){xhr.setRequestHeader(“ Authorization”,“ Basic ” + encodeBase64(“ username:password”));},成功:function(val){// alert(val); alert(“谢谢您的评论!”);}}); `
Patrioticcow

69
beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); };为我工作
Rico Suter 2013年

12
问题...如果我通过的凭据失败,则在Chrome中,将向用户显示一个对话框,以再次输入用户名/密码。如果凭据失败,如何防止出现第二个对话框?
David

2
这样是否会将用户名和密码公开开放给任何人查看?即使它在base64中,他们也可以对其进行解码。与下面的答案相同。
cbron

6
通常,@ calebB基本身份验证只是将用户名和密码保留在开放状态,以供任何人查看。这不仅仅是这里描述的方法的问题。如果使用基本身份验证,或者实际上正在使用任何身份验证,那么也应该使用SSL。
杰森·杰克逊

354

一年如何变化。除了的header属性之外xhr.setRequestHeader,当前的jQuery(1.7.2+)在$.ajax调用中还包含一个username和password属性。

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

从评论和其他答案中进行编辑:要明确-为了抢先发送身份验证而没有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!'); 
  }
});

15
应该username不是user吗?而且也不完全相同:从在线文档和我的经验来看,它似乎并不是某些API所要求的先发制人。换句话说,Authorization仅当返回代码401时,它才发送标头。
Stefano Fratini 2012年

3
@StefanoFratini-您在两个方面都是正确的。修复了用户名字段,并且最好了解抢先式身份验证与仅在质询时进行响应。像在其他答案中一样显式设置标头,将允许使用基本身份验证的“被动”变体。
jmanning2k

对我来说,以上选项没有用,这就像一个魅力..谢谢
Anoop Isaac 2013年

参见上面的评论,请更正此答案以指示{“ Authorization”:“ Basic” + btoa(“ user:pass”)}作为正确的标头
Jay

2
这就是我一直在寻找的答案!对我来说,此答案的关键是如何使用“标头”抢先发送身份验证。我的问题在这里得到了回答。stackoverflow.com/questions/28404452/…–
史蒂文·安德森

63

使用beforeSend回调添加具有身份验证信息的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!'); 
    }
});

4
您应注意,低于10的IE版本和某些移动平台不支持此处用于Base64加密的“ btoa”
SET

1
同样,根据此developer.mozilla.org/en-US/docs/DOM/window.btoa,您应该使用btoa(unescape(encodeURIComponent(str)))
SET

@SET,我想它应该是btoa(encodeURIComponent(escape(str)))
Saurabh Kumar 2014年

我想获得响应,因此摆脱了异步错误,并向成功函数添加了结果参数。我还预先生成了Authorization标头,因此只使用了它。
radtek

1
应注意@ SET,Base64不是加密的,它是编码的。如果是加密的话,用一个函数调用对它进行解码就不是一件那么简单的事
Chris

40

或者,只需使用1.5中引入的headers属性:

headers: {"Authorization": "Basic xxxx"}

参考:jQuery Ajax API


您能告诉我,如何为每个用户执行此操作吗?我的意思是从数据库中获取每个用户的api令牌,并使用ajax标头发送它。
Haniye Shadman

32

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

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

我从Rico和Yossi的答案中得出了上述结论。

BTOA功能的Base64编码字符串。


5
这是一个坏主意,因为您将与所有 AJAX请求一起发送登录信息,而与URL无关。另外,的文档$.ajaxSetup()还说“设置未来Ajax请求的默认值。不建议使用它。
Zero3,2016年

27

就像其他人建议的那样,您可以直接在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标记内,以正确响应预检。

然后发送一些标头,以告知浏览器允许其进行身份验证,并发送 Access-Control-Allow-Origin授予跨站点请求的权限。

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


5
感谢您提供的有关浏览器发送不带身份验证标头的CORS预检请求的信息!这样的细节可能会导致数小时的调试!
jbandi 2014年


11

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

我设法通过在请求中添加用户和密码(例如user:pw@domain.tld)来解决此限制。除Internet Explorer以外,几乎所有浏览器可以使用,在,不支持通过URL进行身份验证(该调用将不会执行)。

请参阅http://support.microsoft.com/kb/834489


猜想从安全角度
出发,

链接断开(404)。
彼得·莫滕森

10

可以通过以下三种方法实现此目的

方法1:

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 
  },
});

方法2:

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 
  },
});

方法3:

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 
  },
});

8

根据SharkAlley的回答,它也可以与nginx一起使用。

我正在寻找一种解决方案,以通过jQuery从位于nginx之后且受基本身份验证限制的服务器获取数据。这对我有用:

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/
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.