jwt是什么

通常情況下葱跋,把API直接暴露出去是風險很大的澳化,不說別的崔步,直接被機器攻擊就喝一壺的。那么一般來說缎谷,對API要劃分出一定的權限級別井濒,然后做一個用戶的鑒權,依據(jù)鑒權結(jié)果給予用戶開放對應的API列林。目前瑞你,比較主流的方案有幾種:

  1. 用戶名和密碼鑒權,使用Session保存用戶鑒權結(jié)果希痴。
  2. 使用OAuth進行鑒權(其實OAuth也是一種基于Token的鑒權者甲,只是沒有規(guī)定Token的生成方式)
  3. 自行采用Token進行鑒權

第一種就不介紹了,由于依賴Session來維護狀態(tài)砌创,也不太適合移動時代虏缸,新的項目就不要采用了。第二種OAuth的方案和JWT都是基于Token的纺铭,但OAuth其實對于不做開放平臺的公司有些過于復雜寇钉。我們主要介紹第三種:JWT。

什么是JWT舶赔?

JWT是 Json Web Token 的縮寫。它是基于 RFC 7519 標準定義的一種可以安全傳輸?shù)?小巧自包含 的JSON對象谦秧。由于數(shù)據(jù)是使用數(shù)字簽名的竟纳,所以是可信任的和安全的。JWT可以使用HMAC算法對secret進行加密或者使用RSA的公鑰私鑰對來進行簽名疚鲤。

JWT的工作流程

下面是一個JWT的工作流程圖锥累。模擬一下實際的流程是這樣的(假設受保護的API在/protected中)

  1. 用戶導航到登錄頁,輸入用戶名集歇、密碼桶略,進行登錄
  2. 服務器驗證登錄鑒權,如果改用戶合法,根據(jù)用戶的信息和服務器的規(guī)則生成JWT Token
  3. 服務器將該token以json形式返回(不一定要json形式际歼,這里說的是一種常見的做法)
  4. 用戶得到token惶翻,存在localStorage、cookie或其它數(shù)據(jù)存儲形式中鹅心。
  5. 以后用戶請求/protected中的API時吕粗,在請求的header中加入 Authorization: Bearer xxxx(token)。此處注意token之前有一個7字符長度的 Bearer
  6. 服務器端對此token進行檢驗旭愧,如果合法就解析其中內(nèi)容颅筋,根據(jù)其擁有的權限和自己的業(yè)務邏輯給出對應的響應結(jié)果。
  7. 用戶取得結(jié)果
image.png

為了更好的理解這個token是什么输枯,我們先來看一個token生成后的樣子议泵,下面那坨亂糟糟的就是了。

eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ3YW5nIiwiY3JlYXRlZCI6MTQ4OTA3OTk4MTM5MywiZXhwIjoxNDg5Njg0NzgxfQ.RC-BYCe_UZ2URtWddUpWXIp4NMsoeq2O6UF-8tVplqXY1-CI9u1-a-9DAAJGfNWkHE81mpnR3gXzfrBAB3WUAg復制代碼

但仔細看到的話還是可以看到這個token分成了三部分桃熄,每部分用 . 分隔肢簿,每段都是用 Base64 編碼的。如果我們用一個Base64的解碼器的話 ( www.base64decode.org/ )蜻拨,可以看到第一部分 eyJhbGciOiJIUzUxMiJ9 被解析成了:

{
    "alg":"HS512"
}復制代碼

這是告訴我們HMAC采用HS512算法對JWT進行的簽名池充。

第二部分 eyJzdWIiOiJ3YW5nIiwiY3JlYXRlZCI6MTQ4OTA3OTk4MTM5MywiZXhwIjoxNDg5Njg0NzgxfQ 被解碼之后是

{
    "sub":"wang",
    "created":1489079981393,
    "exp":1489684781
}復制代碼

這段告訴我們這個Token中含有的數(shù)據(jù)聲明(Claim),這個例子里面有三個聲明:sub, createdexp。在我們這個例子中,分別代表著用戶名英支、創(chuàng)建時間和過期時間敞贡,當然你可以把任意數(shù)據(jù)聲明在這里。

看到這里攀痊,你可能會想這是個什么鬼token,所有信息都透明啊,安全怎么保障咽瓷?別急,我們看看token的第三段 RC-BYCe_UZ2URtWddUpWXIp4NMsoeq2O6UF-8tVplqXY1-CI9u1-a-9DAAJGfNWkHE81mpnR3gXzfrBAB3WUAg舰讹。同樣使用Base64解碼之后茅姜,咦,這是什么東東

D X    ?DmYTe?L?UZcPZ0$gZAY?_7?wY@復制代碼

最后一段其實是簽名月匣,這個簽名必須知道秘鑰才能計算钻洒。這個也是JWT的安全保障。這里提一點注意事項锄开,由于數(shù)據(jù)聲明(Claim)是公開的素标,千萬不要把密碼等敏感字段放進去,否則就等于是公開給別人了萍悴。

也就是說JWT是由三段組成的头遭,按官方的叫法分別是header(頭)寓免、payload(負載)和signature(簽名):

header.payload.signature復制代碼

頭中的數(shù)據(jù)通常包含兩部分:一個是我們剛剛看到的 alg,這個詞是 algorithm 的縮寫计维,就是指明算法袜香。另一個可以添加的字段是token的類型(按RFC 7519實現(xiàn)的token機制不只JWT一種),但如果我們采用的是JWT的話享潜,指定這個就多余了困鸥。

{
  "alg": "HS512",
  "typ": "JWT"
}復制代碼

payload中可以放置三類數(shù)據(jù):系統(tǒng)保留的、公共的和私有的:

  • 系統(tǒng)保留的聲明(Reserved claims):這類聲明不是必須的剑按,但是是建議使用的疾就,包括:iss (簽發(fā)者), exp (過期時間),
    sub (主題), aud (目標受眾)等。這里我們發(fā)現(xiàn)都用的縮寫的三個字符艺蝴,這是由于JWT的目標就是盡可能小巧猬腰。
  • 公共聲明:這類聲明需要在 IANA JSON Web Token Registry 中定義或者提供一個URI,因為要避免重名等沖突猜敢。
  • 私有聲明:這個就是你根據(jù)業(yè)務需要自己定義的數(shù)據(jù)了姑荷。

簽名的過程是這樣的:采用header中聲明的算法,接受三個參數(shù):base64編碼的header缩擂、base64編碼的payload和秘鑰(secret)進行運算鼠冕。簽名這一部分如果你愿意的話,可以采用RSASHA256的方式進行公鑰胯盯、私鑰對的方式進行懈费,如果安全性要求的高的話。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)復制代碼

JWT的生成和解析

為了簡化我們的工作博脑,這里引入一個比較成熟的JWT類庫憎乙,叫 jjwt ( github.com/jwtk/jjwt )。這個類庫可以用于Java和Android的JWT token的生成和驗證叉趣。

JWT的生成可以使用下面這樣的代碼完成:

String generateToken(Map<String, Object> claims) {
    return Jwts.builder()
            .setClaims(claims)
            .setExpiration(generateExpirationDate())
            .signWith(SignatureAlgorithm.HS512, secret) //采用什么算法是可以自己選擇的泞边,不一定非要采用HS512
            .compact();
}復制代碼

數(shù)據(jù)聲明(Claim)其實就是一個Map,比如我們想放入用戶名疗杉,可以簡單的創(chuàng)建一個Map然后put進去就可以了阵谚。

Map<String, Object> claims = new HashMap<>();
claims.put(CLAIM_KEY_USERNAME, username());復制代碼

解析也很簡單,利用 jjwt 提供的parser傳入秘鑰乡数,然后就可以解析token了椭蹄。

Claims getClaimsFromToken(String token) {
    Claims claims;
    try {
        claims = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    } catch (Exception e) {
        claims = null;
    }
    return claims;
}復制代碼

JWT本身沒啥難度,但安全整體是一個比較復雜的事情净赴,JWT只不過提供了一種基于token的請求驗證機制。但我們的用戶權限罩润,對于API的權限劃分玖翅、資源的權限劃分,用戶的驗證等等都不是JWT負責的。也就是說金度,請求驗證后应媚,你是否有權限看對應的內(nèi)容是由你的用戶角色決定的。所以我們這里要利用Spring的一個子項目Spring Security來簡化我們的工作猜极。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末中姜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子跟伏,更是在濱河造成了極大的恐慌丢胚,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件受扳,死亡現(xiàn)場離奇詭異携龟,居然都是意外死亡,警方通過查閱死者的電腦和手機勘高,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門峡蟋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人华望,你說我怎么就攤上這事蕊蝗。” “怎么了赖舟?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵蓬戚,是天一觀的道長。 經(jīng)常有香客問我建蹄,道長碌更,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任洞慎,我火速辦了婚禮痛单,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘劲腿。我一直安慰自己旭绒,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布焦人。 她就那樣靜靜地躺著挥吵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪花椭。 梳的紋絲不亂的頭發(fā)上忽匈,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機與錄音矿辽,去河邊找鬼丹允。 笑死郭厌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的雕蔽。 我是一名探鬼主播折柠,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼批狐!你這毒婦竟也來了扇售?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤嚣艇,失蹤者是張志新(化名)和其女友劉穎承冰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體髓废,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡巷懈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了慌洪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顶燕。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖冈爹,靈堂內(nèi)的尸體忽然破棺而出涌攻,到底是詐尸還是另有隱情,我是刑警寧澤频伤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布恳谎,位于F島的核電站,受9級特大地震影響憋肖,放射性物質(zhì)發(fā)生泄漏因痛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一岸更、第九天 我趴在偏房一處隱蔽的房頂上張望鸵膏。 院中可真熱鬧,春花似錦怎炊、人聲如沸谭企。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽债查。三九已至,卻和暖如春瓜挽,著一層夾襖步出監(jiān)牢的瞬間盹廷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工久橙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留速和,地道東北人歹垫。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓剥汤,卻偏偏與公主長得像颠放,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吭敢,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容