FineReport:任意時刻只允許在一個客戶端登陸賬號的外掛
在使用FineReport報表系統中,處於賬戶安全考慮,有些企業希望同一賬號在任意時刻智慧在統一客戶端登入。那麼當A使用者在C1客戶端登陸後,該賬號又在另外一個C2客戶端登陸,伺服器如何取判斷呢?
開發原理
當伺服器在得知A在C1登陸後,在cookie裡面寫入一個標識ID~將瀏覽器標記,然後以後的訪問自然就能夠根據匹配使用者名稱和對應的標記來確定這個使用者是不是在換瀏覽器登陸了,當匹配到使用者異地登陸,就要把之前已經登陸的使用者先登出,再登陸新請求的使用者。當然關閉頁面事件裡要向後臺先傳送一個請求,後臺要記得清除改使用者標記的快取。
那麼客戶端怎麼知道自己的賬號在異地登陸了呢?
這個就要基於心跳了~因為我們的http不是長連線的,所以只能模擬了,弄一個輪詢ajax不斷的問伺服器,我是否在異地登陸,因為之前伺服器任何一個賬號登陸都會又一個ID標識,那麼當接收到一個客戶端心跳時,我們只要拿出裡面的ID和使用者名稱跟儲存的匹配~匹配到存在該使用者名稱,但是ID不對,那說明一定是另外一個客戶端登陸了這個賬號了,這個時候就告知客戶端,你的賬號已經異地登陸,然後前端提示重新整理就可以了。
如何實現?
這裡要用到FineReport提供的介面,RequestInterceptor
介面內容
點選(此處)摺疊或開啟
-
package com.fr.stable.fun;
-
-
import com.fr.stable.fun.mark.Layer;
-
import com.fr.stable.fun.mark.Mutable;
-
import com.fr.stable.web.RequestCMDReceiver;
-
-
/**
-
* Created by richie on 16/8/9.
-
* 請求攔截器,透過傳遞op和cmd進行內建請求的攔截
-
*/
-
public interface RequestInterceptor extends Mutable, RequestCMDReceiver, Layer {
-
-
String MARK_STRING = "RequestInterceptor";
-
-
int CURRENT_LEVEL = 1;
- }
相關引用類
點選(此處)摺疊或開啟
-
package com.fr.stable.web;
-
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
-
/**
-
* Created by richie on 16/8/9.
-
* 請求接收器
-
*/
-
public interface RequestCMDReceiver {
-
-
/**
-
* cmd引數值
-
* @return cmd引數值
-
*/
-
String getCMD();
-
-
/**
-
* 執行
-
* @param req http請求
-
* @param res http應答
-
* @param sessionID 會話ID
-
* @throws Exception 處理失敗則丟擲異常
-
*/
-
void actionCMD(HttpServletRequest req, HttpServletResponse res,
-
String sessionID) throws Exception;
-
-
/**
-
* 執行請求
-
* @param req http請求
-
* @param res http響應
-
* @throws Exception 處理失敗則丟擲異常
-
*/
-
void actionCMD(HttpServletRequest req, HttpServletResponse res) throws Exception;
- }
註冊方式
點選(此處)摺疊或開啟
-
<extra-core>
-
<RequestInterceptor class="com.fr.plugin.xxx.youclassname" op="fs_load" cmd="login" pid="com.fr.plugin.xxx.name"/>
- </extra-core>
其中pid的值應該和外掛的id值一致,透過這樣的註冊方式,就可以使用自己定義的處理邏輯來覆蓋掉預設的登入驗證請求。
以上,透過故意製造報錯的方式我們能夠看到~FR登陸請求都是繼承於
com.fr.fs.web.service.FSLoadLoginAction 這個類的~、
進一步反編譯JAR可以看到~這個類是繼承於
com.fr.web.core.ActionNoSessionCMD 最後實現 ActionCMD, RequestInterceptor
那麼正好,我們的外掛主類就可以免去很多自己寫,直接繼承於FSLoadLoginAction就可以用來處理所有的自定義登陸請求
【凡是需要在登陸時做得事情都可以在這裡做】
當然actionCMD(HttpServletRequest req, HttpServletResponse res)這個執行方法還是要重寫的~
還有就是protected void signOnSuccess(HttpServletRequest req, HttpServletResponse res, PrintWriter writer, String url)這個登陸成功之後需要做一些上面說的操作~
下面是兩個程式碼片段,主要就是處理登陸標記和登出清除的.
片段1
點選(此處)摺疊或開啟
-
@Override
-
public void actionCMD(HttpServletRequest req, HttpServletResponse res)
-
throws Exception {
-
String username = WebUtils.getHTTPRequestParameter(req, Constants.FR_USERNAME);
-
String heartBeat = WebUtils.getHTTPRequestParameter(req, "__heartbeat__");
-
if(ComparatorUtils.equals(heartBeat, "__active__")){
-
if(StringUtils.isEmpty(username)){
-
username = WebUtils.getHTTPRequestParameter(req, "__username__");
-
if(!StringUtils.isEmpty(username)){
-
req.getSession(true).removeAttribute("__username__");
-
}
-
}
-
//如果使用者名稱不為空且已登入的列表中不包含該使用者名稱說明已經被踢下線
-
if(!StringUtils.isEmpty(username) && !log.containsKey(username)){
-
writeResult(res,false);
-
return ;
-
}
-
//如果在已登入的列表中找到了該使用者名稱的記錄,但是ID不匹配也說明被踢下線了
-
if(log.containsKey(username)){
-
String crtUUID = WebUtils.getHTTPRequestParameter(req, "_sessionid_");
-
SingleLoginBean logBean = log.get(username);
-
String oldId = logBean.getId();
-
if(!ComparatorUtils.equals(crtUUID,oldId)){
-
writeResult(res,false);
-
return;
-
}else{
-
//將當前時刻設定為最近活躍時刻
-
logBean.setWait4removeTime(new Date().getTime());
-
}
-
}
-
writeResult(res,true);
-
//登出太久不活躍的使用者 30S以上
-
checkAllUser();
-
return;
-
}
-
super.actionCMD(req, res);
- }
片段2
點選(此處)摺疊或開啟
-
protected void signOnSuccess(HttpServletRequest req, HttpServletResponse res, PrintWriter writer, String url) throws IOException, JSONException {
-
String username = WebUtils.getHTTPRequestParameter(req, Constants.FR_USERNAME);
-
String uuid = req.getSession(true).getId();
-
SingleLoginBean logBean = new SingleLoginBean(uuid,req,res,req.getSession(true));
-
logBean.setWait4removeTime(new Date().getTime());
-
//後面的使用者登入成功後需要先將舊的使用者轉移到等待刪除的列表中
-
remove4logout(req);
-
//將新登入的使用者新增到已經登入的使用者中
-
log.put(username, logBean);
-
if ("true".equals(WebUtils.getHTTPRequestParameter(req, ParameterConsts.__REDIRECT__))) {
-
res.sendRedirect(url);
-
} else {
-
writer.print(JSONObject.create().put("url", url));
-
}
- }
點選(此處)摺疊或開啟
-
var askServer4Active = function(){
-
var sessionid = getCrtSessionid();
-
if( sessionid == "" || sessionid == null ){
-
return ;
-
}
-
var url = FR.servletURL+"?op=fs_load&cmd=login&__heartbeat__=__active__&_sessionid_="+sessionid;
-
FR.ajax({
-
url: url,
-
type: "POST",
-
dataType:"JSON",
-
success: function(msg){
-
if(!msg.success){
-
if(active){
-
active = false;
-
clearInterval(timer);
-
FR.Msg.alert("警告","您的賬號已在其他客戶端登陸!\n如非本人授權,請及時修改密碼!\n3秒後頁面將跳轉至登陸頁!");
-
setTimeout(function(){
-
document.location = FR.servletURL+"?op=fs";
-
},3000);
-
}
-
}else{
-
active = true;
-
}
-
}
-
});
- };
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21472864/viewspace-2131028/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- linux 關閉只允許SSH登陸(允許使用者名稱、密碼登陸)Linux密碼
- 讓Linux系統允許使用root賬號遠端登入Linux
- NEO 客戶端外掛客戶端
- 設定ssh只允許使用者從指定的ip登陸
- 伺服器安全之 伺服器只允許指定IP登陸伺服器
- 只允許一個程式執行winformORM
- Git多賬號登陸Git
- Linux賬號安全——使用者登陸許可權Linux
- winform只允許一個應用程式執行ORM
- Oracle建立一個schema的只讀賬號Oracle
- 使用 GitLab 賬號登陸 KubeSphereGitlab
- 改造CAS單點登入 --- 自定義登陸頁面(客戶端)客戶端
- Windows2008遠端登陸時提示”要登入到此遠端計算機,您必須被授予允許通過終端登入登入的許可權”Windows計算機
- 客戶端登陸logout操作,事務回滾客戶端Go
- linux下gssftp允許root登陸的設定(轉)LinuxFTP
- 手遊防破解防外掛技術方案(一)客戶端篇客戶端
- CentOS 配置Mysql允許遠端登入CentOSMySql
- 【轉】linux設定金鑰登入(只允許金鑰登入)Linux
- mysql建立只讀賬號和增刪改查許可權賬號MySql
- web專案024-----賬戶登陸Web
- 客戶端使用sysdba許可權登入資料庫客戶端資料庫
- WordPress 外掛 bug 允許攻擊者遠端重置網站內容網站
- windows10登陸的microsoft賬戶如何刪除WindowsROS
- wsus客戶端安裝時的許可權問題客戶端
- 從0開始寫一個基於Flutter的開源中國客戶端(8)——外掛的使用Flutter客戶端
- SSMS18 登陸介面清除不需要的登入賬戶SSM
- 虛擬平臺客戶端無法登陸問題記錄客戶端
- linux 本地賬號密碼無法登陸(shell可以登入),一直返回 登陸的login介面Linux密碼
- win10無法登陸到你的賬戶怎麼辦_win10顯示無法登陸到你的賬戶解決方法Win10
- FastDFS-nginx外掛作為FastDFS客戶端訪問ASTNginx客戶端
- win10 如何選擇其它帳戶登陸 win10怎麼調整登陸賬戶Win10
- microsoft賬戶是幹嘛的 microsoft微軟賬戶申請登陸了有什麼用ROS微軟
- CloudNotes之桌面客戶端篇:外掛系統的實現Cloud客戶端
- html只允許輸入的資料校驗,只允許輸入字母漢字數字等HTML
- ora-01031錯誤(在客戶端以SYS使用者登陸報錯)客戶端
- Dino:一個有著現代外觀的開源 XMPP 客戶端客戶端
- 關於ProFTP v1.2.9客戶端退出登陸顯示資訊的求教(轉)FTP客戶端
- oracle 只讀賬戶的建立Oracle