星期一, 12月 14, 2009

內嵌網頁的系統自動登入

自動登入的方式其實有很多種實作方式,會因為系統的類型而有所不同。如登入電腦時,所有開啟的Client AP或是 Web AP都進入登入狀態,或是像是類似 Facebook在登入後,放在世界各地的AP利用Facebook提供的API確認登入,才讓自己進入登入狀態。

而我介紹的這個方式,是指自己的系統,開了幾個 iframe 視窗,放置不同網址但需要登入的AP系統。而我們設計簡單的紀錄該系統的帳號密碼,再登入我們的系統的時候,也一併登入那些系統。


首先要先了解一個 Javascript 的觀念。iframe 文件內載入完成的觸發處理。

<body>
<
script>
var 
iframe document.createElement("iframe");
iframe.src "http://127.0.0.1/login.php";
document.body.appendChild(iframe);
if (
iframe.attachEvent) { // IE
    
iframe.attachEvent("onload", function() {
                                
//  do something
                                
});
} else if (
iframe.addEventListener) { // Firefox
    
iframe.addEventListener("load", function() {
                                
//  do something
                                
}, true);
} else {
    
iframe.onload = function () { // 其他的瀏覽器
       //  do something
    
};
}
</script>
</body>



我們可以看到程式碼中首先動態建立一個 iframe 視窗,並且指定 src 網址為
 http://127.0.0.1/login.php 這個網頁。當 iframe 內載入完成時,會依照瀏覽器的事件內的function 內作處理。

接下就是實作,隱藏式網頁POST資料到異系統(帳號密碼登入),當資料送出到異系統登入頁程式後,在這個隱藏式網頁載入完畢(ifrmae 載入完畢),便可以將內嵌視窗直接導引到正式的程式頁面(這時已為登入狀態了)。

<body>
<
div id=hdiv></div>
<
script>
document.getElementById("hdiv").innerHTML "<iframe name=hiddenFrame id=hiddenFrame src=''></iframe>"
// 動態建立表單,模擬登入表單資料
var form document.createElement("form")
document.body.appendChild(form);
with (form) {
    
method 'POST'
    
target 'hiddenFrame'
    
action 'http://192.168.1.3/login.php'
    
userText document.createElement("input")
    
userText.type 'hidden'
    
userText.name "user"
    
userText.value "noon"
    
appendChild(userText)
    
passTextdocument.createElement("input")
    
passText.type 'hidden'
    
passText.name  "passwd"
    
passText.value "test"
    
appendChild(passText)
}
// 將資料送到登入頁
form.submit();

var 
gotoFrame document.createElement("iframe");
document.body.appendChild(gotoFrame);
var 
iframe document.getElementById("hiddenFrame")
// 登入頁載入完成,表示 cookie 已寫入,則將網頁連結導到 ap 程式頁
if (iframe.attachEvent) { // IE
    
iframe.attachEvent("onload", function() {
                                 
gotoFrame.src "http://192.168.1.3/ap.php";
                                 });
} else if (
iframe.addEventListener) { // Firefox
    
iframe.addEventListener("load", function() {
                                    
gotoFrame.src "http://192.168.1.3/ap.php";
                                    }, 
true);
} else {
    
iframe.onload = function () { // 其他的瀏覽器
        
gotoFrame.src "http://192.168.1.3/ap.php";
    };
}
</script>
</body>


其實理論上到這樣就可以了,但是 IE 6.0 的安全性作了一些改變。請看這裡

在frameset 或是 iframe 還是新的彈跳視窗,是會拒絕cookie的。 所以被內嵌的視窗,可以主動丟出 HTTP Header =>  P3P: CP="CAO PSA OUR"


附上上面範例程式用的登入程式,和應用程式的PHP程式碼。
login.php
<?php
header
('P3P: CP="CAO PSA OUR"');
if (
$_POST['user'] && $_POST['passwd']) {
        
setCookie('USER'$_POST['user']);
        echo 
"<META HTTP-EQUIV='REFRESH' CONTENT='0; URL=".$_SERVER['PHP_SELF']."'>";
        exit;
}
echo 
$_COOKIE['LOGIN'];
?>
<form method=post>
<input type=text name=user>
<input type=password name=passwd><input type=submit value=ok>
</form>


ap.php
<?php
echo "USER:".$_COOKIE['USER'];
?>

註:使用 Ajax 連到不同網域是會出現安全性警告的,而這個方式則不會。
註:這個範例可以應用在傳送資料到別的網域系統上而不被察覺。
註:這個範例解決內嵌視窗的登入問題。
註:這個範例也提供判斷內嵌式窗載入完成作後續動作的方式。

沒有留言:

張貼留言

我的意見