开发者

Use basic authentication with jQuery and Ajax

开发者 https://www.devze.com 2023-02-21 10:59 出处:网络
I am trying to create a basic authentication through the browser, but I can\'t really get there. If this script won\'t be he开发者_开发知识库re the browser authentication will take over, but I want t

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

If this script won't be he开发者_开发知识库re 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!');
    }
});


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

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


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


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


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.


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.


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

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


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


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.


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

精彩评论

暂无评论...
验证码 换一张
取 消