<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java軟件報表軟件技術博客

    java報表軟件技術匯總 java報表軟件制作 報表軟件新聞
    posts - 355, comments - 100, trackbacks - 0, articles - 3
       :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理

    在使用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));

            }


        }


    下面就是JS輪詢了

    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;

                                    }


                            }
      

                    }
    ); 

            }
    ;

     



    主站蜘蛛池模板: 亚洲男人天堂2017| 亚洲AV无码一区二区三区久久精品 | 蜜芽亚洲av无码精品色午夜| 67pao强力打造国产免费| 亚洲欧美成人综合久久久| 亚洲一区二区精品视频| 3344免费播放观看视频| 女人裸身j部免费视频无遮挡| 亚洲AV永久纯肉无码精品动漫| 成人免费毛片观看| 国产成人免费ā片在线观看老同学| 亚洲毛片无码专区亚洲乱| 免费国产高清视频| 69免费视频大片| 麻豆安全免费网址入口| 亚洲成A∨人片在线观看无码| 亚洲国产a级视频| 色se01短视频永久免费| 男女一进一出抽搐免费视频| 国产成人精品日本亚洲专一区| 狠狠综合久久综合88亚洲| 西西大胆无码视频免费| 欧洲人成在线免费| 综合一区自拍亚洲综合图区| 亚洲日本一区二区三区| 亚洲色偷拍区另类无码专区| 毛片a级三毛片免费播放| 很黄很污的网站免费| 男人免费视频一区二区在线观看| 亚洲国产成人精品电影| 亚洲VA中文字幕不卡无码| 四只虎免费永久观看| 免费大片黄在线观看yw| a在线视频免费观看| 国产天堂亚洲国产碰碰| 国产成人精品日本亚洲专一区| 亚洲三级电影网址| 亚洲精品高清国产一线久久| 亚洲?v女人的天堂在线观看| 日韩精品视频免费在线观看| 男女超爽刺激视频免费播放|