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

I am trying to create a basic authentication through the browser, but I can't really get there.

If this script won't be here the browser authentication will take over, but I want to tell the browser that the user is about to make the authentication.

The address should be something like:

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

I have a form:

<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>

And a script:

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

转载于:https://stackoverflow.com/questions/5507234/use-basic-authentication-with-jquery-and-ajax

weixin_41568127
?yb? If you need to integrate with a third party API behind authentication (which is what I am trying to do - developer.zendesk.com/rest_api/docs/core/…)
接近 4 年之前 回复
csdnceshi77
狐狸.fox So you don't want the browser to handle the BASIC authentication? Why not just use form-based authentication?
9 年多之前 回复

10个回答

Use jQuery's beforeSend callback to add an HTTP header with the authentication information:

beforeSend: function (xhr) {
    xhr.setRequestHeader ("Authorization", "Basic " + btoa(username + ":" + password));
},
csdnceshi56
lrony* Basic authentication in general just leaves the username and password in the open for anyone to see. This isn't just a problem with the method described here. If basic authentication, or really any authentication is being used then SSL should also be employed.
大约 6 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Won't this leave the username and password out in the open for anyone to see ? Even if its in base64 they can just decode it. Same with the answer below.
大约 6 年之前 回复
csdnceshi50
三生石@ Problem...If the credentials I pass fail, in Chrome the user is then presented with a dialog to enter username/pwd again. How can I prevent this 2nd dialog from appearing if the credentials fail?
大约 7 年之前 回复
weixin_41568127
?yb? beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); }; works for me
7 年多之前 回复
csdnceshi51
旧行李 i am using the example u gave but it doesn't work $.ajax ({ url: "server.in.local/index.php", beforeSend: function (xhr) { xhr.setRequestHeader(“Authorization”, “Basic ” + encodeBase64 (“username:password”) );}, succes: function(val) { //alert(val); alert("Thanks for your comment!"); } });
9 年多之前 回复

How things change in a year. In addition to the header attribute in place of xhr.setRequestHeader, current jQuery (1.7.2+) includes a username and password attribute with the $.ajax call.

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

EDIT from comments and other answers: To be clear - in order to preemptively send authentication without a 401 Unauthorized response, instead of setRequestHeader (pre -1.7) use 'headers':

$.ajax
({
  type: "GET",
  url: "index1.php",
  dataType: 'json',
  headers: {
    "Authorization": "Basic " + btoa(USERNAME + ":" + PASSWORD)
  },
  data: '{ "comment" }',
  success: function (){
    alert('Thanks for your comment!'); 
  }
});
csdnceshi62
csdnceshi62 you saved our life!
大约 2 年之前 回复
csdnceshi69
YaoRaoLov This is the answer for which I have been looking! The key bit in this answer for me is how the 'header' is used to preemptivly send authentication. My question here is answered by this. stackoverflow.com/questions/28404452/…
5 年多之前 回复
csdnceshi71
Memor.の I think the latest jQuery supports setRequestHeader instead of 'headers'
大约 6 年之前 回复
weixin_41568196
撒拉嘿哟木头 See above comment, please correct this answer to indicate { "Authorization": "Basic " + btoa("user:pass") } as the correct header
6 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 for me the the above option didnt work, this worked like a charm.. thanks
接近 7 年之前 回复
csdnceshi50
三生石@ - you are correct on both counts. Fixed the username field, and it's good to know about the preemptive auth vs responding only on challenge. Setting the header explicitly as in other answers will allow use of this 'passive' variant of basic auth.
接近 8 年之前 回复
weixin_41568208
北城已荒凉 Shouldn't it be username and not user? Also it's not exactly the same: from the online docos and my experience it looks like it's not preemptive as some APIs require. In other words it sends the Authorization header only when a code 401 is returned.
接近 8 年之前 回复

There are 3 ways to achieve this as shown below

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

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

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

Use the jQuery ajaxSetup function, that can set up default values for all ajax requests.

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

JSONP does not work with basic authentication so the jQuery beforeSend callback won't work with JSONP/Script.

I managed to work around this limitation by adding the user and password to the request (e.g. user:pw@domain.tld). This works with pretty much any browser except Internet Explorer where authentication through URLs is not supported (the call will simply not be executed).

See http://support.microsoft.com/kb/834489.

csdnceshi79
python小菜 The link is broken (404).
2 年多之前 回复
weixin_41568126
乱世@小熊 guess that security-wise it's a sane choice to not allow this
大约 3 年之前 回复
csdnceshi61
derek5. does not work on safari either
接近 4 年之前 回复

According to SharkAlley answer it works with nginx too.

I was search for a solution to get data by jQuery from a server behind nginx and restricted by Base Auth. This works for me:

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

And the JavaScript code is:

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

Article that I find useful:

  1. This topic's answers
  2. http://enable-cors.org/server_nginx.html
  3. http://blog.rogeriopvl.com/archives/nginx-and-the-http-options-method/

Or, simply use the headers property introduced in 1.5:

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

Reference: jQuery Ajax API

The examples above are a bit confusing, and this is probably the best way:

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

I took the above from a combination of Rico and Yossi's answer.

The btoa function Base64 encodes a string.

weixin_41568196
撒拉嘿哟木头 This is a bad idea, because you will send the login information with all AJAX requests, regardless of URL. Also, the documentation for $.ajaxSetup() says "Set default values for future Ajax requests. Its use is not recommended."
4 年多之前 回复

Use the beforeSend callback to add a HTTP header with the authentication information like so:

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!'); 
    }
});
csdnceshi76
斗士狗 Thank you Adrian. I must have an error in my code (missing Auth header). And yes, I'll need to allow CORS on the API.
3 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Access-Control-Allow-Origin errors occur when cross-origin HTTP requests (CORS) aren't permitted. It's not related to Authorization header. Is your API on the same domain as the web page? If not you will need to allow CORS on the API.
3 年多之前 回复
csdnceshi76
斗士狗 I am trying this and I do not see the Authorization header being set in the request (when I look at the headers actually being sent using the network tab). And I get an error in the console: "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin is therefore not allowed access." So I don't know if the lack of Authorization in the request is causing that or something else?
3 年多之前 回复
csdnceshi57
perhaps? is should be noted the Base64 is not encryption, it's encoding. If it was encryption, it wouldn't be super simple to decode it with a single function call
大约 5 年之前 回复
weixin_41568196
撒拉嘿哟木头 I wanted to get the response so got rid of async false, and added result parameter to success function. I also had pre-generated Authorization header so just used that instead.
大约 6 年之前 回复
csdnceshi55
~Onlooker i guess it needs to be btoa(encodeURIComponent(escape(str)))
6 年多之前 回复
csdnceshi70
笑故挽风 also, according to this developer.mozilla.org/en-US/docs/DOM/window.btoa you should use btoa(unescape(encodeURIComponent(str)))
7 年多之前 回复
csdnceshi70
笑故挽风 you should notice that "btoa" used here for Base64 encryption is not supported in IE versions less that 10 and in some mobile platforms
7 年多之前 回复

As others have suggested, you can set the username and password directly in the Ajax call:

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

OR use the headers property if you would rather not store your credentials in plain text:

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

Whichever way you send it, the server has to be very polite. For Apache, your .htaccess file should look something like this:

<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

Explanation:

For some cross domain requests, the browser sends a preflight OPTIONS request that is missing your authentication headers. Wrap your authentication directives inside the LimitExcept tag to respond properly to the preflight.

Then send a few headers to tell the browser that it is allowed to authenticate, and the Access-Control-Allow-Origin to grant permission for the cross-site request.

In some cases, the * wildcard doesn't work as a value for Access-Control-Allow-Origin: You need to return the exact domain of the callee. Use SetEnvIf to capture this value.

csdnceshi67
bug^君 Thanks for the info that browsers send a CORS preflight request without auth headers! Details like this can cause hours of debugging!
6 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐