What I am trying to do is to have a page on the HTTP protocol sending an AJAX call to the same Web server but using HTTPS. Both the requesting page and the AJAX handler are on the same server, having the same domain and port. (I.e., only difference is the protocol.) To illustrate,
From http://www.example.com/index.php
Triggers a jQuery AJAX call to https://www.example.com/authenticate.php?user=123&password=456
(I am hoping to pass the password through HTTPS to make it encrypted over the Internet. Due to some design constraints I must use AJAX call instead of redirecting the page.)
I understand that there is a CORS issue here and thus I researched a bit and found that I could actually make use of the Access-Control-Allow-Origin header to help. I then set the following in my Apache's configuration file,
Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers "content-type, accept"
Header set Access-Control-Max-Age 1000
I can see that when the browser requests the resources from the server, the headers can be seen. Request:
Accept */*
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Authorization Basic Y2FzZXRhZ3JhbWRldjpwYXNzd29yZGRldiE=
Cache-Control no-cache
Connection keep-alive
Cookie __utma=99230732.2019724749.1337107099.1337849971.1337856946.9; __utmz=99230732.1337107099.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=217650581.954519005.1337107174.1337772401.1337777327.5; __utmz=217650581.1337107174.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=99230732; PHPSESSID=m8lnqhqv2qa6f884a8um413n81
Host www.example.com
Pragma no-cache
Referer http://www.example.com/index.php
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0
The response is like,
Accept-Ranges bytes
Access-Control-Allow-Head... content-type, accept
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... *
Access-Control-Max-Age 1000
Connection close
Content-Length 16599
Content-Type application/x-javascript
Date Thu, 24 May 2012 14:48:17 GMT
Etag "48157-40d7-4c0c938b220c0"
Last-Modified Thu, 24 May 2012 14:39:39 GMT
Server Apache/2.2.3 (CentOS)
So it looks like the header part is fulfilled. (Am I right?)
Then when I tried to call the follow jQuery AJAX code in JavaScript,
$.ajax({
// Use HTTPS as there is password transferred
url : "https://www.example.com/authentication.php",
type : 'POST',
dataType : 'json',
async : false,
data : ajaxData,
beforeSend : function(xhr, opt) {},
error : function(error) {
console.log("Ajax error: unable to login user: ");
console.log(error);
},
success : function(status) {
if(status==USER_AUTH_AUTHENTICATE_USER_SUCCESS) {
console.log("User login succeeded!");
} else {
console.log("User login failed.");
}
}
});
The browser (FireFox 12) will just return an object,
readyState 0
status 0
statusText "[Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js Line: 8240"]"
Is there something that I missed out?
In fact I had already tried a lot of suggestions from forums and blogs trying to get this done but still I am unsuccessful. I also tried using JSONP and it works fine on FireFox but failed on Chrome/Safari with no readable error message but just throwing an error from jQuery code "head.insertBefore( script, head.firstChild );".
Appreciate much if someone can give me a clue on what is wrong with my code/settings.
Thanks!
As suggested I read this reference case (http://stackoverflow.com/questions/5750696/how-to-get-a-cross-origin-resource-sharing-cors-post-request-working) and I found that it linked to this case (http://stackoverflow.com/questions/5584923/a-cors-post-request-works-from-plain-javascript-but-why-not-with-jquery) as well which is related. I tried the sample XHR code there,
var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', 'https://www.example.com/controllers/Authentication.php', true);
request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");};
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);
The code is called from a page with HTTP protocol. Once the code is executed, the error below is thrown right away,
Access to restricted URI denied...test_xhr.php Line 11
(If I change the HTTPS in JavaScript HTTP, the script works right away and so there should not be any syntax problem or so.)
The request and response headers of the page itself are as follows. Request is,
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Authorization Basic Y2FzZXRhZ3JhbWRldjpwYXNzd29yZGRldiE=
Cache-Control no-cache
Connection keep-alive
Cookie __utma=99230732.2019724749.1337107099.1337856946.1337921578.10; __utmz=99230732.1337107099.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=217650581.954519005.1337107174.1337772401.1337777327.5; __utmz=217650581.1337107174.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=99230732; PHPSESSID=ktd6anojfi40ohemlujosdmhi4
Host www.example.com
Pragma no-cache
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0
The response is,
Access-Control-Allow-Head... content-type, accept
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... *
Access-Control-Max-Age 1000
Connection close
Content-Length 590
Content-Type text/html; charset=UTF-8
Date Fri, 25 May 2012 12:24:44 GMT
Server Apache/2.2.3 (CentOS)
X-Powered-By PHP/5.1.6
So I am just thinking something is fundamentally wrong with my setup but not jQuery as native XHR does not work as well. :(
You have two issues:
1) Access-Control-Allow-Origin "*" is not working with authenticated calls, instead of * reflect the calls Access-Control-Request-Origin or Origin header fields.
2) You'll need Access-Control-Allow-Credentials: true in the response.
Other things that might help: setting authorization header manually, assembling name and password with base64. This is the surest way to have working. Its advantage is its drawback: setting authorization header manually activates the OPTIONS header based CORS handshake. (All your requests are preceded with an OPTIONS request that you have to also handle) This one seems to have a coherent implementation across all modern browsers (IE9 of course is an exception, IE10 however works allegedly).
HTH
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With