淺顯易懂了解token單點登入原理及實現過程

什麼是單點登入(SSO)

首先舉個例子:
對於某個銀行系統,本身有開發自己的系統,比如門戶之類的。最近有新的新的需求,比如數據分析的業務需求,於是購買了一套數據分析系統、,之後又上線了一套貸款系統等等,如下圖。那麼用戶在在登入操作的時候,就會面臨一個問題,多個系統之間是不是需要登入多次呢?
在這裏插入圖片描述
比如我從門戶頁面進入系統,接下來要在貸款系統上進行操作,那是不是又要輸入一次用戶名、密碼?如果沒有密碼的話肯定會有安全問題。這時候就要用到SSO單點了,只需要在門戶首頁登入一次,在各個系統中可以進行免登入操作。

單點登錄(Single Sign On),簡稱爲 SSO,在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。

常見的SSO有token回調、Oauth、cas,同時還可以集成在第三方系統上,比如微信、釘釘等。這篇文章主要介紹token單點登入。

token單點原理

在這裏插入圖片描述
a、首先要求用戶登入自己的系統(銀行系統),然後打開第三方系統,比如通過url訪問第三方系統,在訪問的時候攜帶上token(一般是作爲參數直接拼接在url上);
b、當第三方系統接收到一個未登入的請求時,會調用客戶系統(銀行系統或者獨立的驗證系統)提供接口對這個token進行校驗,如果檢驗成功,則返回用戶信息(比如用戶id,登入name),驗證失敗則跳轉到錯誤頁面;
c、第三方系統(數據分析系統)拿到這些信息後,對該請求根據返回的用戶名進行登入處理。

對於自己的系統來說,需要完成的工作是:提供一個驗證token的接口,在跳轉到第三方系統時生成token並且放到請求中。對於第三方系統來說,需要開發一個攔截請求然後判斷登入的邏輯(常見的處理方式是 過濾器)。

安全性

1、在整個過程中是沒有用戶名和密碼的傳遞的,不會存在密碼被盜用的風險;
2、對於自己的系統來說,不會讓第三方公司知道自己的加密策略的加密手段,因爲生成token和驗證token的過程都是在自己系統上進行,第三方系統並不關心這個過程是如何進行的,只需要返回一個驗證結果就行了;
3、比較擔心的是token如果被攔截獲取,是不是就可以從別的地方根據這個token登入第三方系統了呢?
分情況討論吧:
a、首先一般這個token是一串很長的字符串,憑肉眼記憶幾乎是不可能的,被盜的情況應該是這臺電腦中病毒,從而請求被攔截並獲取盜這些參數。對於內網環境、或者安全級別比較高的辦公環境來說,這種可能性很小;
b、token往往具有時效性、一般有效期在2~3分鐘(每個廠子的安全策略不同,控制的時間也不同),即使被拷貝給其他人,很快也會失效;
c、更高級的做法,就是token只能檢驗一次,然後就會被回收,這樣幾乎不存在泄露的問題。

token生成機制有很多,比如 通過MD5來進行加密得到加密串,md5(用戶名 + 時間戳 + key)、或者hash算法生成等等。

代碼演示

客戶的回調接口java代碼舉例
public class TokenCheckServlet extends HttpServlet {

 private static final long serialVersionUID = 1L;

    
   public TokenCheckServlet() {

       super();

   }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         String token = request.getParameter("token");
         if(token == null || "".equals(token.trim())) {
                //token不存在處理邏輯
         return;
         }
         else {
                 // 校驗token是否合法
                 StringBuilder result = new StringBuilder();
                 
                 if(check(token)) {
                 //token驗證通過就返回當前登錄用戶
                  result.append("{\"result\":\"success\",\"userId\":\"test\"}");
                 }
                 else {
                   // token驗證沒通過就不返回userId。
                   result.append("{\"error\":\"james\"}");
                 }

                 response.getWriter().write(result.toString());
         }
 }

 
/**
*校驗tokan是否有效
*/
 private boolean check(String token) {
        return true;
 }
 
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request, response);
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章