CAS身份验证和使用jQuery AJAX重定向

时间:2010-06-02 19:42:05

标签: authentication redirect jquery

我有一个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调用没有处理重定向的问题,还是这里有更多的问题而不是眼睛?

3 个答案:

答案 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&param2=true

jQuery $.ajax$.post

请注意,如果您不需要传递用户名和密码,那么GET请求就足够了。

$.ajax({
    type : "POST",
    url : "http://" + document.domain +
        "/wsproxy.php?url=http://wsToCall.com/ws/resource?param1=false&param2=true",
    dataType : "json",
    success : handleRedirects,
    data: { username: "foo", password: "bar" }
});