一、問題描述
OA 系統與報表系統整合,將報表繫結在 OA 系統的節點上,對於 OA 系統中想實現對 FineReport 的單點登入,使用者需要在 OA 的登入介面中將使用者名稱和密碼傳入到報表的認證地址進行認證,若 OA 系統和報表系統不是部署在同一臺伺服器上,在進行登入時進行跨域,那麼要如何透過 Ajax 實現 OA 系統和報表系統的跨域登入呢?
Ajax:即“Asynchronous Javascript And XML”(非同步 JavaScript 和 XML),是指一種建立互動式網頁應用的網頁開發技術。透過在後臺與伺服器進行少量資料交換,Ajax 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。
iframe 方式和 Ajax 方式的區別:
iframe 方式和 Ajax 方式均可以實現跨域單點登入,Ajax 可以實現非同步的單點登入,並且可對報表系統驗證的結果進行處理,如登入超時,但是 iframe 不可以非同步處理,並且在進行報表驗證的時候,無法對驗證的結果進行處理。
二、實現思路
Ajax 登入方式天然支援跨域,故在 OA 系統的登入介面中直接透過 Ajax 將使用者名稱密碼傳送到報表伺服器進行後臺驗證,則可解決跨域單點登入問題。
三、示例
透過簡化的 OA 登入頁面說明ajax的實現步驟。
1
Ajax 實現步驟。
登陸按鈕事件設定。
使用者輸入使用者名稱密碼後點擊提交或登入按鈕時,觸發 doSubmit() 方法,該方法中實現登入事件並且透過 Ajax 將使用者名稱密碼傳送到報表系統進行驗證,並且在驗證成功時,觸發 HTML 中的表單提交事件,實現登入成功頁面的跳轉,實現報表認證程式碼如下。
注1:由於使用了 Ajax,需要引入 jquery.js。
注2:如果在 Win8 下單點登入異常,在 Ajax 傳遞使用者名稱密碼的時候轉碼一下即可,比如說fine_password":encodeURIComponent(password)。
function doSubmit() { var username = document.getElementById("username").value.trim(); var password = document.getElementById("password").value.trim(); if (username === "") { window.alert("請輸入使用者名稱"); return false; } if (password === "") { window.alert("請輸入密碼"); return false; } var url = "http://localhost:8080/webroot/decision/login/cross/domain" + "?fine_username=" + username + "&fine_password=" + password + "&validity=" + -1; jQuery.ajax({ url: url,//單點登入的管理平臺報表伺服器 timeout: 5000,//超時時間(單位:毫秒) dataType:"jsonp",//跨域採用jsonp方式 jsonp:"callback", success: function (res) { console.log(res); if (res.errorCode) { window.alert(res.errorMsg); }else { // 儲存token並跳轉到對應連結 window.location.href = "http://localhost:8080/webroot/decision"; } }, error: function () { alert("超時或伺服器其他錯誤");// 登入失敗(超時或伺服器其他錯誤) } });}<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
2
完整程式碼。
將上述 Ajax 單點登入的提交事件放到原來 OA 系統登入頁面中,是指點選登入按鈕時,觸發該事件,修改後即可以實現跨域單點非同步登入的程式碼如下。
注:使用者名稱密碼錶單中使用 button 來觸發 doSubmit(),您只要將 doSubmit() 方法加入到您的 OA 的登入頁面中即可,為了簡化操作,上面的完整程式碼沒有跳轉到指定頁面,而是跳轉到平臺頁面。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; " charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
function doSubmit() {
var username = document.getElementById("username").value.trim();
var password = document.getElementById("password").value.trim();
if (username === "") {
window.alert("請輸入使用者名稱");
return false;
}
if (password === "") {
window.alert("請輸入密碼");
return false;
}
var url = "http://localhost:8080/webroot/decision/login/cross/domain" + "?fine_username=" + username + "&fine_password=" + password + "&validity=" + -1;
alert(url);
jQuery.ajax({
url: url,//單點登入的管理平台報表伺服器
timeout: 5000,//超時時間(單位:毫秒)
dataType:"jsonp",//跨域采用jsonp方式
jsonp:"callback",
success: function (res) {
console.log(res);
if (res.errorCode) {
window.alert(res.errorMsg);
}else {
// 保存token并跳轉到對應鏈接
window.location.href = "http://localhost:8080/webroot/decision";
}
},
error: function () {
alert("超時或服務器其他錯誤");// 登入失敗(超時或伺服器其他錯誤)
}
});
}
</script>
</head>
<body>
<p>請登入</p>
<form id="login" name="login" method="POST" action="">
<p>使用者名稱:<input id="username" type="text" name="username"/></p>
<p>密 碼:<input id="password" type="password" name="password"/></p>
<input type="button" value="登入" onClick="doSubmit()"/>
</form>
</body>
</html>
四、登出使用者
當登出專案使用者時,同時也希望登出報表使用者名稱的 Session,這時可在點選退出按鈕時的同時也可以實現 FR 報表的退出登入。
jQuery.ajax({
url:"http://localhost:8075/webroot/decision/logout/cross/domain",//單點登錄的報表服務器
dataType:"jsonp",//跨域採用jsonp方式
jsonp:"callback",
timeout:5000,//超時時間(單位:毫秒)
success:function(data) {
if (data.status === "success") {
//登出成功
}
},
error:function(){
// 登出失敗(超時或伺服器其他錯誤)
}
});
五、安全性
報表透過 URL 傳使用者名稱和密碼進行驗證,傳到報表伺服器是以 Session 的方式儲存,防止被人中途攔截會導緻系統洩密,可以對登入進來的密碼進行加密,可參考文件 密碼加密設定;或者使用 https 證書,讓請求在傳輸過程中加密,配置方法也很簡單,修改下伺服器的配置檔案就行了。這種方式還存在一個證書合法性問題,用自己生成的證書,客戶端在訪問報表中瀏覽器會顯示證書非法警告,所以需要去購買合法證書。目前國內最便宜的證書一年是一千多元。
六、注意事項
跨域單點登入需改將【管理系統】→【安全管理】→【安全防護】的【內容嗅探攻擊防護】以及【點選劫持攻擊防護】關閉,否則會報錯,如下圖所示: