首頁>技術>

最近在網上和朋友聊天,發現他在資料介面中校驗登入狀態用的還是session,在我及時勸說和科普之後,他最終決定改用JWT,那麼接下來我們就聊一聊資料介面應該怎麼管理登入狀態以及什麼是JWT

前後端混合開發的場景

前後端混合開發的時候,使用者登入狀態的是通過session來實現的,原理很簡單:使用者登入後,服務端將登入使用者資訊儲存到伺服器上的指定位置,並生成對應的session id儲存到瀏覽器的cookie中。需要校驗的時候先讀取cookie中的session id,找到伺服器中對應的儲存內容,完成校驗。大家可以明顯的感知到,這個機制是建立在cookie基礎上的,cookie又依賴於瀏覽器,而且有域名限制。是不適合app、小程式、以及前後端時資料介面採用其他域名等情況的,那麼app、小程式要怎麼做呢,接下來我會為大家講解

App與小程式前後端分離的場景

app、小程式、前後端分離時的資料介面一般採用token來做登入資訊校驗。原理是使用者登入後,服務端生成對應使用者的一個token(一般都是唯一的指定位數的字串)後返回,前端拿到token後儲存,在需要校驗使用者登入的介面請求中加入token(可以是get、post引數的形式),服務端拿到token校驗真實性、有效性等資訊後完成登入校驗。一般為了防止盜用,還會設定一套簽名校驗的過程。

其實token和session的原理是差不多的,都是服務端將對應使用者的一個key【sessionId,token】交給前端,前端通過token請求服務端,服務端拿到token再去驗證合法有效性,之後反查使用者,獲取使用者登入資訊。

那麼針對上述2中驗證機制,一般我們的app前後端分離,或者接入第三方系統的時候往往會使用到,例如微信,微博,保利威視等介面都是通過這張方式去驗證登入狀態的。當然這種方式也是有缺點的,下面我們來聊一聊上述方式的不足之處:

1、服務端必須儲存token,以及有效期,校驗的時候必須要有資料讀取的過程;2、校驗簽名的時候一般需要一個secret做為加簽欄位,前端必須也要同時儲存這個secret,這樣顯然不適合程式碼會暴露的網頁前端。

下面我們來聊一聊JWT

什麼是JWT

JWT是JSON Web Token的簡稱,有官網詳細介紹,大家可以看一看,這裡只是簡單描述一下。 JWT其實就是一種特殊的token,原理和使用方法自然和token一樣。 JWT是由三部分組成的字串,結構是:頭部+主體內容(官方稱之為Payload【載荷】)+簽名,三部分用“.”連線。頭部和主體內容都是json格式的字串再經過base64編碼,為了方便放在get請求中,還需要把類似“=”、“/”等特殊字元替換掉。

頭部內容是固定的,原始json就是下面這樣{"alg": "HS256","typ": "JWT"}
中間的主體內容Payload,原始json一般是類似下面這樣的{"userName": "alipeng","expTime": "2020-01-06 05:00:18"}

主體內容一個是當前登入的使用者,可以是使用者名稱稱,使用者的唯一id;還有一個就是過期時間expTime。當然還可以加入一些其他不私密的和系統相關的初始化資訊,注意,不要在JWT的payload或header中放置敏感資訊,除非它們是加密的;

下面我來聊聊簽名與認證流程

,那麼為了得到簽名部分,你必須有編碼過的header、編碼過的payload、一個祕鑰,簽名演算法是header中指定的那個,然對它們簽名即可。

例如:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

簽名的主要作用是用於驗證訊息在傳遞過程中有沒有被更改,並且,對於使用私鑰簽名的token,它還可以驗證JWT的傳送方是否為它所稱的傳送方,看下面官網給出的一張圖你就明白了:

簽名解析

下面是一張官網的認證圖:

JWT認證流程

服務端拿到JWT之後可以在不讀取資料的情況下,僅通過解碼這部分資訊就可以完成獲取登入使用者以及判斷是否過期等工作,這一點就優於我們上述講解的session的方式;

最後的簽名一般是把頭部、主體內容再加上secret拼接成字串再加密,這一步在使用者登入生成JWT的時候就完成了。服務端拿到JWT之後只需要把前兩部分加上secret再計算一次簽名加以比對就可以完成校驗簽名,前端不需要同時儲存secret,這樣也提高了安全性!

@Test public void gen1() throws IOException { String token =""; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //日期轉字串 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND,30 ); //特定時間的年後 Date date = calendar.getTime(); try { Algorithm algorithm = Algorithm.HMAC256("mysecrite"); token = JWT.create() .withIssuer("alipeng") .withSubject("xiaoming") .withClaim("name", 123) .withArrayClaim("array", new Integer[]{1, 2, 3}) .withExpiresAt(date) .sign(algorithm); System.out.println("loglogagel:"+token); } catch (UnsupportedEncodingException exception){ //UTF-8 encoding not supported } catch (JWTCreationException exception){ //Invalid Signing configuration / Couldn't convert Claims. } }最後再聊聊JWT的一些缺點

目前想到以下幾點:1、安全性:簽名包含在token中,一旦token整體被盜用,將沒有辦法區分;

2、過期時間放在token中而不是服務端儲存處理,一旦token生成並簽發出去,將無法靈活的控制有效期;

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 複雜分散式架構下的計算治理之路:計算中介軟體 Linkis