首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web 限制使用者重複登入實作:單一帳號單一登入機制

     編輯:Java 相關知識

業務場景與解決思路

需求:使用者在 A 處登入後,若在 B 處再次登入,A 處應被強制下線。採用「後登入者踢除先登入者」策略。

  1. 使用全域 Map<String, String> 保存 loginId -> sessionId,新登入直接覆蓋舊值。
  2. 實作 HttpSessionListener,在 Session 銷毀時移除 Map 中對應項目。
  3. 實作 Filter 攔截請求,驗證當前 Session ID 是否為 Map 中最新值,否則執行登出並導向登入頁提示。

核心類別實作

1. 登入用戶 Map 管理類

public class LoginUserMap {
    private static Map<String, String> loginUsers = new ConcurrentHashMap<>();

    public static void setLoginUsers(String loginId, String sessionId) {
        loginUsers.put(loginId, sessionId);
    }
    public static Map<String, String> getLoginUsers() { return loginUsers; }
    public static void removeUser(String sessionId) {
        loginUsers.entrySet().removeIf(entry -> sessionId.equals(entry.getValue()));
    }
    public static boolean isInLoginUsers(String loginId, String sessionId) {
        return loginUsers.containsKey(loginId) && sessionId.equals(loginUsers.get(loginId));
    }
}

2. 登入處理 (在 Controller 中)

HttpSession session = request.getSession();
LoginUserMap.setLoginUsers(username, session.getId());

3. Session 監聽器

@WebListener
public class SessionListener implements HttpSessionListener {
    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        LoginUserMap.removeUser(event.getSession().getId());
    }
}

4. 登入限制過濾器

@WebFilter(urlPatterns = "/*")
public class LoginLimitFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);

        if (session != null) {
            IUser user = UserUtils.getCurrUserInfo(); // 專案自有工具類
            if (user != null) {
                String loginId = user.getLoginId();
                if (!LoginUserMap.isInLoginUsers(loginId, session.getId())) {
                    // 被踢下線處理
                    logout(); // 自有登出邏輯
                    response.sendRedirect(request.getContextPath() + "?logoutway=edge");
                    return;
                }
            }
        }
        chain.doFilter(req, res);
    }
}

前端提示 (JavaScript)

window.onload = function() {
    if (GetQueryString('logoutway')) {
        layer.alert('該賬號已在其他地方登錄,您已被迫下線...', {
            skin: 'layui-layer-lan', title: '提示', closeBtn: 0
        }, function() {
            var url = window.location.href;
            window.location.href = url.substr(0, url.indexOf('?logoutway=edge'));
        });
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved