首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

SSO 單點登錄實戰(一):基於 Cookie + Filter 跨域自動登錄完整實現

     編輯:C++ 入門

SSO 單點登錄落地實戰:Cookie 跨域共享 + Filter 自動登錄架構詳解

單點登錄(SSO)核心課題是:多子系統如何共享登錄狀態。本文基於「主域名相同、子域名不同」場景(如 www.bbs.itcast.cn、www.news.itcast.cn),詳細實現基於 Cookie 跨域共享 + Filter 自動登錄的完整方案,並對比 CAS 標準流程。

核心技術方案

  1. Cookie 作用域設置:path=/(全路徑有效)+ domain=.itcast.cn(主域名共享,覆蓋所有子域名)
  2. 生命周期控制:未勾選「記住我」→ 會話級 Cookie(瀏覽器關閉失效);勾選 → 持久化 Cookie(如 7 天)
  3. Filter 自動登錄攔截:每請求檢查 Session,無則讀取 Cookie 解析用戶信息寫入 Session
  4. 統一登出:清除 Session + 設置 Cookie maxAge=0 刪除 Cookie

環境準備:Hosts 配置

# C:\Windows\System32\drivers\etc\hosts
127.0.0.1 localhost
127.0.0.1 www.bbs.itcast.cn
127.0.0.1 www.news.itcast.cn
127.0.0.1 www.server.com  # SSO 認證中心

核心代碼實現

1. 登錄 Servlet(統一認證入口)

public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        String nm = req.getParameter("name");
        String pwd = req.getParameter("pwd");
        String chk = req.getParameter("chk"); // 是否記住 7 天
        
        String forward = "/index.jsp";
        // 簡單驗證:用戶名以 it 開頭,密碼以 pwd 開頭
        if (nm != null && nm.startsWith("it") && pwd != null && pwd.startsWith("pwd")) {
            forward = "/jsps/welcome.jsp";
            // 關鍵:無論是否記住,都寫入 Cookie 保證跳轉時攜帶
            Cookie cookie = new Cookie("autologin", nm + "@" + pwd);
            cookie.setPath("/");
            cookie.setDomain(".itcast.com"); // 跨子域名共享
            if (chk != null) { // 勾選記住我
                cookie.setMaxAge(60 * 60 * 24 * 7); // 7 天秒數
            }
            resp.addCookie(cookie);
            req.getSession().setAttribute("user", nm);
        }
        req.getRequestDispatcher(forward).forward(req, resp);
    }
}

2. 自動登錄 Filter(核心攔截器)

public class AutoLogin implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpSession session = request.getSession();
        
        // 已登錄直接放行
        if (session.getAttribute("user") != null) {
            chain.doFilter(req, resp);
            return;
        }
        
        // 嘗試從 Cookie 自動登錄
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie ck : cookies) {
                if ("autologin".equals(ck.getName())) {
                    String[] vals = ck.getValue().split("@");
                    session.setAttribute("user", vals[0]); // 寫入 Session
                    break;
                }
            }
        }
        chain.doFilter(req, resp);
    }
    // init/destroy 略
}

web.xml 配置:<filter-mapping><url-pattern>/*</url-pattern></filter-mapping> 全路徑攔截。

3. 安全登出 Servlet

public class LoginOutServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        // 刪除 Cookie:同名、同路徑、同域、maxAge=0
        Cookie cookie = new Cookie("autologin", "");
        cookie.setPath("/");
        cookie.setDomain(".itcast.com");
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
        
        session.removeAttribute("user");
        resp.sendRedirect(req.getContextPath() + "/index.jsp");
    }
}

CAS 標準流程對比(web.xml 片段)

<filter>
    <filter-name>CAS Authentication Filter</filter-name>
    <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
    <init-param><param-name>casServerLoginUrl</param-name><param-value>https://www.server.com:8080/login</param-value></init-param>
    <init-param><param-name>serverName</param-name><param-value>https://www.bbs.com:8080</param-value></init-param>
</filter>
<filter>
    <filter-name>CAS Validation Filter</filter-name> ...
</filter>
<filter-mapping><filter-name>CAS Authentication Filter</filter-name><url-pattern>/protected/*</url-pattern></filter-mapping>
<filter-mapping><filter-name>CAS Validation Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

關鍵差異:CAS 採用「集中式認證中心 + Ticket 驗證 + 代理回調」模式,更安全、支持單點登出、代理認證,但部署複雜;Cookie+Filter 方案輕量、易理解、適合中小型同域系統。

單點登出機制深度解析(CAS)

  • SessionMappingStorage:HashMap 存儲 sessionId ↔ Ticket 映射
  • SingleSignOutHttpSessionListener:Session 銷毀時清理映射
  • SingleSignOutFilter:攔截登出請求,通知 CAS Server 廣播登出通知
  • SimpleServerLogoutHandler:將本地登出轉發至 CAS Server

總結與建議

維度Cookie + FilterCAS 標準
部署複雜度低(單應用內完成)高(獨立 CAS Server)
跨域支持同主域名子域名任意域名(需 HTTPS)
安全性中(Cookie 明文傳輸)高(Ticket 一次性、加密傳輸)
單點登出需自行實現廣播內置支持
適用場景內部系統、同域子系統、快速原型企業級、異構系統、高安全要求

下篇將展示 CAS 完整流程圖與效果演示。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved