<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 五、實現 只是簡要介紹下基于java的實現過程,不提供完整源碼,明白了原理,我相信你們可以自己實現。sso采用客戶端/服務端架構,我們先看sso-client與sso-server要實現的功能(下面:sso認證中心=sso-server) sso-client 1. 攔截子系統未登錄用戶請求,跳轉至sso認證中心 2. 接收并存儲sso認證中心發送的令牌 3. 與sso-server通信,校驗令牌的有效性 4. 建立局部會話 5. 攔截用戶注銷請求,向sso認證中心發送注銷請求 6. 接收sso認證中心發出的注銷請求,銷毀局部會話 sso-server 1. 驗證用戶的登錄信息 2. 創建全局會話 3. 創建授權令牌 4. 與sso-client通信發送令牌 5. 校驗sso-client令牌有效性 6. 系統注冊 7. 接收sso-client注銷請求,注銷所有會話   接下來,我們按照原理來一步步實現sso吧! 1、sso-client攔截未登錄請求   java攔截請求的方式有servlet、filter、listener三種方式,我們采用filter。在sso-client中新建LoginFilter.java類并實現Filter接口,在doFilter()方法中加入對未登錄用戶的攔截 ``` public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(); if (session.getAttribute("isLogin")) { chain.doFilter(request, response); return; } //跳轉至sso認證中心 res.sendRedirect("sso-server-url-with-system-url"); } ``` 2、sso-server攔截未登錄請求   攔截從sso-client跳轉至sso認證中心的未登錄請求,跳轉至登錄頁面,這個過程與sso-client完全一樣 3、sso-server驗證用戶登錄信息   用戶在登錄頁面輸入用戶名密碼,請求登錄,sso認證中心校驗用戶信息,校驗成功,將會話狀態標記為“已登錄” ``` @RequestMapping("/login") public String login(String username, String password, HttpServletRequest req) { this.checkLoginInfo(username, password); req.getSession().setAttribute("isLogin", true); return "success"; } ``` 4、sso-server創建授權令牌   授權令牌是一串隨機字符,以什么樣的方式生成都沒有關系,只要不重復、不易偽造即可,下面是一個例子 `String token = UUID.randomUUID().toString();` 5、sso-client取得令牌并校驗   sso認證中心登錄后,跳轉回子系統并附上令牌,子系統(sso-client)取得令牌,然后去sso認證中心校驗,在LoginFilter.java的doFilter()中添加幾行 ``` // 請求附帶token參數 String token = req.getParameter("token"); if (token != null) { // 去sso認證中心校驗token boolean verifyResult = this.verify("sso-server-verify-url", token); if (!verifyResult) { res.sendRedirect("sso-server-url"); return; } chain.doFilter(request, response); } ``` verify()方法使用httpClient實現,這里僅簡略介紹,httpClient詳細使用方法請參考官方文檔 ``` HttpPost httpPost = new HttpPost("sso-server-verify-url-with-token"); HttpResponse httpResponse = httpClient.execute(httpPost); ``` 6、sso-server接收并處理校驗令牌請求   用戶在sso認證中心登錄成功后,sso-server創建授權令牌并存儲該令牌,所以,sso-server對令牌的校驗就是去查找這個令牌是否存在以及是否過期,令牌校驗成功后sso-server將發送校驗請求的系統注冊到sso認證中心(就是存儲起來的意思)   令牌與注冊系統地址通常存儲在key-value數據庫(如redis)中,redis可以為key設置有效時間也就是令牌的有效期。redis運行在內存中,速度非常快,正好sso-server不需要持久化任何數據。   令牌與注冊系統地址可以用下圖描述的結構存儲在redis中,可能你會問,為什么要存儲這些系統的地址?如果不存儲,注銷的時候就麻煩了,用戶向sso認證中心提交注銷請求,sso認證中心注銷全局會話,但不知道哪些系統用此全局會話建立了自己的局部會話,也不知道要向哪些子系統發送注銷請求注銷局部會話 ![](https://box.kancloud.cn/89d3b44561c38cf5cc2fa5713a7ac87a_337x147.png) 7、sso-client校驗令牌成功創建局部會話   令牌校驗成功后,sso-client將當前局部會話標記為“已登錄”,修改LoginFilter.java,添加幾行 ``` if (verifyResult) { session.setAttribute("isLogin", true); } ```   sso-client還需將當前會話id與令牌綁定,表示這個會話的登錄狀態與令牌相關,此關系可以用java的hashmap保存,保存的數據用來處理sso認證中心發來的注銷請求 8、注銷過程   用戶向子系統發送帶有“logout”參數的請求(注銷請求),sso-client攔截器攔截該請求,向sso認證中心發起注銷請求 ``` String logout = req.getParameter("logout"); if (logout != null) { this.ssoServer.logout(token); } ```   sso認證中心也用同樣的方式識別出sso-client的請求是注銷請求(帶有“logout”參數),sso認證中心注銷全局會話 ``` @RequestMapping("/logout") public String logout(HttpServletRequest req) { HttpSession session = req.getSession(); if (session != null) { session.invalidate();//觸發LogoutListener } return "redirect:/"; } ```   sso認證中心有一個全局會話的監聽器,一旦全局會話注銷,將通知所有注冊系統注銷 ``` public class LogoutListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent event) {} @Override public void sessionDestroyed(HttpSessionEvent event) { //通過httpClient向所有注冊系統發送注銷請求 } } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看