操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    在傳統的項目中,同一賬戶是允許多人同時登錄在線的,有的使用場景恰恰是不允許多人同時在線的,那么我們可以通過 Shiro 來控制并發登錄,并實現后登錄的用戶,擠掉前面登錄的用戶

    package com.asurplus.common.shiro;
    import com.asurplus.system.entity.SysUserInfo;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.mgt.DefaultSessionKey;
    import org.apache.shiro.session.mgt.SessionManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.filter.AccessControlFilter;
    import org.apache.shiro.web.util.WebUtils;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.Serializable;
    import java.util.Deque;
    import java.util.LinkedList;
    /**
     * 同一用戶登錄后踢出前面的用戶
     */
    public class KickoutSessionFilter extends AccessControlFilter {
        /**
         * 踢出后到的地址
         */
        private String kickoutUrl;
        /**
         * 踢出之前登錄的/之后登錄的用戶 默認踢出之前登錄的用戶
         */
        private boolean kickoutAfter = false;
        /**
         * 同一個帳號最大會話數 默認1
         */
        private int maxSession = 1;
        /**
         * session管理器
         */
        private SessionManager sessionManager;
        /**
         * 緩存管理器
         */
        private Cache> cache;
        public void setKickoutUrl(String kickoutUrl) {
            this.kickoutUrl = kickoutUrl;
        }
        public void setKickoutAfter(boolean kickoutAfter) {
            this.kickoutAfter = kickoutAfter;
        }
        public void setMaxSession(int maxSession) {
            this.maxSession = maxSession;
        }
        public void setSessionManager(SessionManager sessionManager) {
            this.sessionManager = sessionManager;
        }
        public void setCacheManager(CacheManager cacheManager) {
            this.cache = cacheManager.getCache("kickoutSession");
        }
        /**
         * 是否允許訪問
         */
        @Override
        protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
            return false;
        }
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            Subject subject = getSubject(request, response);
            if (!subject.isAuthenticated() && !subject.isRemembered()) {
                // 如果沒有登錄,直接進行之后的流程
                return true;
            }
            Session session = subject.getSession();
            SysUserInfo object = (SysUserInfo) SecurityUtils.getSubject().getPrincipal();
            Serializable sessionId = session.getId();
            // 同步控制
            Deque deque = cache.get(object.getAccount());
            if (deque == null) {
                deque = new LinkedList();
                cache.put(object.getAccount(), deque);
            }
            // 如果隊列里沒有此sessionId,且用戶沒有被踢出;放入隊列
            if (!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
                deque.push(sessionId);
            }
            // 如果隊列里的sessionId數超出最大會話數,開始踢人
            while (deque.size() > maxSession) {
                Serializable kickoutSessionId = null;
                // 如果踢出后者
                if (kickoutAfter) {
                    kickoutSessionId = deque.removeFirst();
                }
                // 否則踢出前者
                else {
                    kickoutSessionId = deque.removeLast();
                }
                try {
                    Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
                    if (kickoutSession != null) {
                        // 設置會話的kickout屬性表示踢出了
                        kickoutSession.setAttribute("kickout", true);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 如果被踢出了,直接退出,重定向到踢出后的地址
            if (session.getAttribute("kickout") != null) {
                // 會話被踢出了
                try {
                    subject.logout();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                saveRequest(request);
                HttpServletRequest httpRequest = WebUtils.toHttp(request);
                // 如果是ajax請求
                if (isAjax(httpRequest)) {
                    HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
                    // 使得http會話過期
                    httpServletResponse.sendError(0);
                    return false;
                } else {
                    WebUtils.issueRedirect(request, response, kickoutUrl);
                    return false;
                }
            }
            return true;
        }
        /**
         * 判斷是否為ajax請求
         *
         * @param request
         * @return boolean對象
         */
        public static boolean isAjax(ServletRequest request) {
            return "XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request).getHeader("X-Requested-With"));
        }
    }
    

    這里我們使用了 ,我們需要在 shiro-.xml 配置文件中,加一個存儲對象,如下:

    
        
    

    /**
    * 并發登錄控制
    *
    * @return
    */
    @Bean
    public KickoutSessionFilter kickoutSessionControlFilter() {
       KickoutSessionFilter kickoutSessionControlFilter = new KickoutSessionFilter();
       // 用于根據會話ID,獲取會話進行踢出操作的;
       kickoutSessionControlFilter.setSessionManager(sessionManager());
       // 使用cacheManager獲取相應的cache來緩存用戶登錄的會話;用于保存用戶—會話之間的關系的;
       kickoutSessionControlFilter.setCacheManager(ehCacheManager());
       // 是否踢出后來登錄的,默認是false;即后者登錄的用戶踢出前者登錄的用戶;
       kickoutSessionControlFilter.setKickoutAfter(false);
       // 同一個用戶最大的會話數,默認1;比如2的意思是同一個用戶允許最多同時兩個人登錄;
       kickoutSessionControlFilter.setMaxSession(1);
       // 被踢出后重定向到的地址;
       kickoutSessionControlFilter.setKickoutUrl("/login?kickout=1");
       return kickoutSessionControlFilter;
    }
    

    其中用到的 管理器,和 管理器在之前的博客中都有講到,本次不再贅述

    我們將踢出的用戶重定向到登錄界面,并攜帶參數

    /**
     * 地址過濾器
     *
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 設置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 設置登錄url
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 設置主頁url
        shiroFilterFactoryBean.setSuccessUrl("/");
        // 設置未授權的url
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        // 自定義攔截器限制并發人數
        LinkedHashMap filtersMap = new LinkedHashMap<>();
        // 限制同一帳號同時在線的個數
        filtersMap.put("kickout", kickoutSessionControlFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);
        Map filterChainDefinitionMap = new LinkedHashMap<>();
        // 注銷登錄
        filterChainDefinitionMap.put("/loginOut", "logout");
        // 開放登錄接口
        filterChainDefinitionMap.put("/doLogin", "anon");
        // 開放獲取登錄驗證碼接口
        filterChainDefinitionMap.put("/kaptcha/**", "anon");
        // 開放Api接口
        filterChainDefinitionMap.put("/api/**", "anon");
        // 開放微信接口
        filterChainDefinitionMap.put("/weixin/**", "anon");
        // 開放websocket接口
        filterChainDefinitionMap.put("/websocket/**", "anon");
        // 開放接口文檔
        filterChainDefinitionMap.put("/doc.html", "anon");
        filterChainDefinitionMap.put("/service-worker.js", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        // 開放靜態資源
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/layui/**", "anon");
        filterChainDefinitionMap.put("/layuimini/**", "anon");
        filterChainDefinitionMap.put("/module/**", "anon");
        filterChainDefinitionMap.put("/upload/**", "anon");
        // 其余url全部攔截,必須放在最后
        filterChainDefinitionMap.put("/**", "kickout,user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    

    我們在 an 對象中注入了自定義過濾器java踢出已登錄用戶,并在最后的地址攔截規則中增加了 ,即使我們開啟了記住登錄功能,該用戶也會被踢下線

    我們在登錄頁面中,需要獲取地址中是否有 參數

    // 是否被擠下線
    if(location.href.indexOf("kickout") > 0){
        setTimeout(function () {
            layNotify.notice({
                title: "登錄提示",
                type: "error",
                message: '您的賬戶已在另一臺設備上登錄,如非本人操作,請立即修改密碼!'
            });
        }, 1000)
    }
    

    這樣后面登錄的用戶就會擠掉前面登錄用戶java踢出已登錄用戶,導致前面登錄的用戶被踢下線了

    如您在閱讀中發現不足,歡迎留言!!!

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有