1. 程式人生 > >Java單點登錄學習心得

Java單點登錄學習心得

pan 登錄失敗 cnblogs png 生成 封裝 思路 任務管理器 方法

什麽是單點登錄?

  SSO(Single Sign On)單點登錄是實現多個系統之間統一登錄的驗證系統,簡單來說就是:有A,B,C三個系統,在A處登錄過後,再訪問B系統,B系統就已經處於了登錄狀態,C系統也是一樣。舉個生活中栗子:你同時打開天貓和淘寶,都進入login界面,都要求你登錄的,現在你在淘寶處登錄後,直接在天貓處刷新,你會發現,你已經登錄了,而且就是你在淘寶上登錄的用戶。說明他們實現了SSO,並且持有相同的信息。

整體流程

技術分享圖片

編碼實現(結尾貼代碼)

1.工程創建

  • 創建一個JAVA模塊,在這個模塊下創建3個web應用,其中一個當作單點登錄服務器sso_server,另外2個分別當作2個應用app1和app2
  • 創建基本目錄和包結構,並導入依賴的jar包
  • 配置不同端口的tomcat服務器

2.實現思路

  1. 第一次訪問App1或App2登錄受限的頁面時,使用過濾器將其全部重定向到單點登錄服務器的登錄頁面,並帶上本應用域名標識來源(以下假設請求來源app1,默認登錄成功是/index)
  2. 單點登錄服務器重寫LoginServlet中init和service方法,在init方法中獲取在xml中配置的需要實現單點登錄服務器的域名信息,用逗號分割
  3. service方法用來處理請求
    1. 當請求是/ssoLogin,也就是app1重定向過來的,將請求轉發到/login.jsp,顯示登錄頁面
    2. 當請求是/login,也就是用戶提交表單,模擬登錄,登錄失敗,轉發到/login.jsp,轉發前往request作用域添加請求來源信息,然後添加到登錄表單隱藏域
      中用於下次判斷,
    3. 登錄成功,直接重定向到對應來源的應用登錄成功頁面--帶上登錄標識UUID生成或者其他方式以及其他應用地址(需要進行字符串替換,過濾掉自己)
  4. 然後請求回到了app1下的/index,經過過濾器的驗證(後面這裏會修改)交給app1的MainServlet處理,重寫service方法,用來處理請求
    1. 當請求是/index,說明是單點登錄過來的,同時帶上了登錄標識flag和其他應用域名信息domains(逗號分割的字符串),這裏將其拆分,用一個線程池去並發通知其他應用執行設置Cookies操作,帶上操作標識和登錄標識,通知完回到本應用默認首頁
    2. 這裏封裝了一個方法syncCookies(server, flag, "setCookie");
    3. 別的應用也需要調用setCookies方法,所以要配置相關訪問路徑做相應處理
  5. 這個時候有Cookies了,需要考慮Cookies存在的情況登錄判斷,修改app1中的過濾器
    1. 從Cookies中獲取登錄標識,判斷是否超時
    2. 重新獲取登錄標識,沒有重定向到sso服務器的登錄
    3. 有則重新設置cookies,‘:‘帶上過期時間用於下次判斷
    4. cookies中不存在登錄標識.請求參數也沒有,重定向到sso服務器的登錄頁
    5. cookies中不存在登錄標識.請求參數中有,重新設置cookies帶上過期時間
  6. 退出實現
    1. 當請求是/ssoLogout,,使用過濾器將其全部重定向到單點登錄服務器的退出,並帶上本應用域名標識來源(應該在帶上用戶標識表明是那個用戶,這裏簡化不作處理)
    2. 單點登錄服務器service方法處理退出請求,重定向到來源應用的退出,並帶上其他應用域名信息用於通知
    3. 然後回到了app1下的MainServlet中service方法處理請求
    4. 退出刪除cookies中的登錄標識(這裏設置一個新的cookies為空,有效期為0,覆蓋掉原來的cookies),然後調用一個線程池去並發通知其他應用執行移除Cookies操作,帶上操作標識和登錄標識,通知完回到本應用退出登錄頁,
    5. syncCookies(server, "", "removeCookie");
    6. 別的應用也需要調用removeCookie方法,所以要配置相關訪問路徑做相應處理

總結

  • 單點登錄服務器需要實現的操作
    • 配置需要單點登錄的應用域名信息
    • 登錄頁/ssoLogin
    • 登錄提交/login
      • 成功重定向到對應來源的應用登錄成功頁面--帶上登錄標識以及其他應用地址
      • 失敗 往request作用域添加請求來源信息添加到隱藏域中用於下次判斷,轉發到登錄頁
    • 退出登錄/ssoLogout
      • 重定向到來源應用的退出,並帶上其他應用域名信息用於通知
  • 各應用服務器需要實現的操作(app1和app2代碼基本一樣只是配置本應用域名不同)
    •   過濾器Filter
      • 配置sso_server地址和本應用地址,過濾全部請求
      • 退出請求,則重定向到sso_server服務器的退出
      • 判斷cookies有沒有登錄標識,是否過期,
        • cookies有但過期了,
          • 請求參數中無登錄標識,重定向到sso_server服務器的登錄頁
          • 請求參數中有登錄標識,則重新設置cookies和過期時間
        • cookies沒有
          • 請求參數中無登錄標識,重定向到sso_server服務器的登錄頁
          • 請求參數中有登錄標識,則重新設置cookies和過期時間
  • Servlet
    • 重寫service方法處理請求
    • sso_server認證成功回到/index請求(app1默認首頁),如果是第一次登錄,會從請求參數中獲取登錄標識和需要通知的其他應用地址,將地址拆分,並發通知其他應用設置cookies信息
    • 可能是你通知我,也可能是我通知你,所以本應用也要實現setCookies操作
    • 如果是退出請求/logout,同理也需要通知其他應用刪除cookies
    • 本應用也要實現removeCookies操作

遇到的問題

1.IDEA調試無法啟動報錯Unable to open debugger port (127.0.0.1:51554): java.net.SocketException "socket closed"

  暴力解決方法:幹掉所有的java進程,重新啟動即可,任務管理器結束掉所有的 java.exe進程

2. 線程池的創建方式,在使用阿裏巴巴代碼規範插件檢查時,發現並不推薦使用

 private ExecutorService service = Executors.newFixedThreadPool(10);
//提示信息:不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險

  解決方案:http://www.cnblogs.com/javanoob/p/threadpool.html

代碼下載地址:sso.rar

Java單點登錄學習心得