我有一个HTML页面需要使用jQuery AJAX函数向受CAS保护的(Central Authentication Service)Web服务发出请求。我有以下代码:
$.ajax({
type: "GET",
url: request,
dataType: "json",
complete: function(xmlHttp) {
console.log(xmlHttp);
alert(xmlHttp.status);
},
success: handleRedirects
});
request
变量可以是CAS服务器(https://cas.mydomain.com/login?service=myServiceURL
),也可以直接到服务(然后应该重定向回CAS以获取服务票证)。 Firebug显示正在进行请求,并以302重定向的形式返回。但是,$.ajax()
函数不处理重定向。
我写了这个函数来解决这个问题:
var handleRedirects = function(data, textStatus) {
console.log(data, textStatus);
if (data.redirect) {
console.log("Calling a redirect: " + data.redirect);
$.get(data.redirect, handleRedirects);
} else {
//function that handles the actual data processing
gotResponse(data);
}
};
但是,即使这样,handleRedirects
函数也永远不会被调用,xmlHttp.status
总是会返回0
。它看起来也不像是通过cas.mydomain.com调用发送的。 (有关类似问题,请参阅this question。)
这是AJAX调用没有处理重定向的问题,还是这里有更多的问题而不是眼睛?
答案 0 :(得分:5)
确实有更多的事情要发生,而不是满足于眼睛。
经过一番调查后,看来这样做的jQuery AJAX请求如果不是同一个子域就会失败。在此示例中,正在从其他服务器向cas.mydomain.com
发出请求。即使它也在mydomain.com
,请求也会失败,因为子域与不匹配。
jQuery AJAX确实正确处理重定向。我在同一个子域上使用脚本进行了一些测试来验证。此外,cookie也会按预期传递。有关此项研究,请参阅my blog post。
另请注意,协议必须相同。也就是说,由于cas.mydomain.com
正在使用HTTPS,因此您调用它的页面也必须使用HTTPS,否则请求将失败。
答案 1 :(得分:1)
浏览器不允许跨域调用。最简单的方法是在移动应用程序端使用JSONP并使用CAS网关返回票证。
答案 2 :(得分:1)
您可以使用PHP代理进行此类跨域AJAX调用。在以下示例中,代理能够调用返回JSON字符串的REST Web服务。
<强> wsproxy.php 强>
<?php
if (!isset($_POST["username"]) || !isset($_POST["password"]))
die("Username or password not set.");
$username = $_POST["username"];
$password = $_POST["password"];
if (!isset($_GET['url'])
die("URL was not set.");
//Rebuild URL (needed if the url passed as GET parameter
//also contains GET parameters
$url = $_GET['url'];
foreach ($_GET as $key => $value) {
if ($key != 'url') {
$url .= "&" . $key . "=" . $value;
}
}
//Set username and password for HTTP Basic Authentication
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("$username:$password")
)
));
//Call WS
$json = file_get_contents($url, false, $context);
// Read HTTP Status
if(isset($http_response_header[0]))
list($version,$status_code,$msg) =
explode(' ',$http_response_header[0], 3);
// Check HTTP Status
if($status_code != 200) {
if($status_code == 404) {
die("404 - Not Found");
} else {
die($status_code . " - Error");
}
}
//Add content header
header('Content-Type: application/json');
print $json;
?>
网址使用
http://yourDomain.com/wsproxy.php?url=https://wsToCall.com/ws/resource?param1=false¶m2=true
请注意,如果您不需要传递用户名和密码,那么GET请求就足够了。
$.ajax({
type : "POST",
url : "http://" + document.domain +
"/wsproxy.php?url=http://wsToCall.com/ws/resource?param1=false¶m2=true",
dataType : "json",
success : handleRedirects,
data: { username: "foo", password: "bar" }
});