你需要了解的token,Json web token(jwt)

tips:接下去會在github寫博客,簡書不再更新和修改文章,歡迎大家逛逛我的新博客點擊查看 ,我會盡量用更容易理解的方式寫好每一篇博客,大家一起學習交流??。

前一個項目用的是cookie+session,由于想試試新花樣,現在這個項目用的是Json web token。也做一下總結。

講Json web token 之前先來了解下什么是token,因為jwt本質就是一個token

什么token

token的意思是“令牌”,是用戶身份的驗證方式,最簡單的token組成:uid(用戶唯一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以哈希算法壓縮成一定長的十六進制字符串,可以防止惡意第三方拼接token請求服務器)。還可以把不變的參數也放進token,避免多次查庫

什么是JSON Web Token

JSON web Token,簡稱JWT,本質是一個token,是一種緊湊的URL安全方法,用于在網絡通信的雙方之間傳遞。一般放在HTTP的headers 參數里面的authorization里面,值的前面加Bearer關鍵字和空格。除此之外,也可以在url和request body中傳遞。

JSON Web Token的組成

一個JWT實際上就是一個字符串,它由三部分組成,頭部、載荷與簽名依順序用點號(".")鏈接而成:1.header,2.payload,3.signature。

頭部(Header)里面說明類型和使用的算法,比如:

{
  "alg": "HS256",
  "typ": "JWT"
}

說明是JWT(JSON web token)類型,使用了HMAC SHA 算法。然后將頭部進行base64加密(該加密是可以對稱解密的),構成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

載荷(Payload)載荷就是存放有效信息的地方,含三個部分:

1.標準中注冊的聲明,2.公共的聲明,3.私有的聲明

1.標準中注冊的聲明 (建議但不強制使用) :

  • iss: jwt簽發者
  • sub: jwt所面向的用戶
  • aud: 接收jwt的一方
  • exp: jwt的過期時間,這個過期時間必須要大于簽發時間
  • nbf: 定義在什么時間之前,該jwt都是不可用的.
  • iat: jwt的簽發時間
  • jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。

2.公共的聲明 :
公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密.

3.私有的聲明 :
私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味著該部分信息可以歸類為明文信息。

定義一個payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后將其進行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

把場景2的操作描述成一個json對象。其中添加了一些其他的信息,幫助今后收到這個JWT的服務器理解這個JWT。 當然,你還可以往載荷放非敏感的用戶信息,比如uid

signature

這個部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,然后通過header中聲明的加密方式進行加鹽secret組合加密,然后就構成了jwt的第三部分。

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret');//TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意secret是保存在服務器端的,jwt的簽發生成也是在服務器端的,secret就是用來進行jwt的簽發和jwt的驗證,所以,它就是你服務端的私鑰,在任何場景都不應該流露出去。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發jwt了。

將這三部分用.連接成一個完整的字符串,構成了最終的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

應用場景:

1.瀏覽器將用戶名和密碼以post請求的方式發送給服務器。

2.服務器接受后驗證通過,用一個密鑰生成一個JWT。

3.服務器將這個生成的JWT返回給瀏覽器。

4.瀏覽器存儲JWT并在使用時將JWT包含在authorization header里面,然后發送請求給服務器。

5.服務器可以在JWT中提取用戶相關信息。進行驗證。

6.服務器驗證完成后,發送響應結果給瀏覽器。

jwt 相比 session 的有點在哪

  • 能解決csrf淺談CSRF攻擊方式
  • 因為json的通用性,所以JWT是可以進行跨語言支持的,像JAVA,JavaScript,NodeJS,PHP等很多語言都可以使用。
  • 因為有了payload部分,所以JWT可以在自身存儲一些其他業務邏輯所必要的非敏感信息。
  • 便于傳輸,jwt的構成非常簡單,字節占用很小,所以它是非常便于傳輸的。
  • 它不需要在服務端保存會話信息, 所以它易于應用的擴展

安全相關

  • 不應該在jwt的payload部分存放敏感信息,因為該部分是客戶端可解密的部分。
  • 保護好secret私鑰,該私鑰非常重要。
  • 建議的方式是通過SSL加密的傳輸(https協議),從而避免敏感信息被嗅探。

代碼實例

客戶端 這里引用axios

axios.interceptors.request.use(
    config => {
        const token = localStorage.getItem('userToken');
        if (token) {
            config.headers.common['Authorization'] = 'Bearer ' + token;
        }
        return config;
    },
    error => {
        return Promise.reject(error);
    }
);

后端(koa) 這里引用jsonwebtoken 這個npm包

登錄時生成一個token

const jwt = require("jsonwebtoken");
const secret = require("../config").secret;

const token = jwt.sign(payload, secret, {
    expiresIn: Math.floor(Date.now() / 1000) + 24 * 60 * 60 // 一天
});

寫一個jwt驗證的中間件

/**
 * @file 處理jwt驗證的中間件
 */

const jwt = require("jsonwebtoken");
const secret = require("../config").secret;

module.exports = async function(ctx, next) {
    // 同步驗證
    const auth = ctx.get('Authorization')
    const token = auth.split(' ')[1];
    try {
        //解碼取出之前存在payload的user_id 和 name
        const payload = jwt.verify(token, secret)
        ctx.user_id = payload.id;
        ctx.name = payload.name;
        await next()
    } catch (err) {
        ctx.throw(401, err)
    }
}

在路由(koa-router)這邊使用這個中間件

const verify = require('../middlewares/verify');
router.post('/register', register) //注冊
    .post('/login', login) //登錄
    .get('/message', verify, message) // 獲取首頁列表信息

其他

還有一個 oauth token :一個關于授權(authorization)的開放網絡標準協議。

有一個"云沖印"的網站,可以將用戶儲存在Google的照片,沖印出來。用戶為了使用該服務,必須讓"云沖印"讀取自己儲存在Google上的照片。

具體看這個 理解OAuth 2.0

參考閱讀&&鳴謝:

什么是 JWT -- JSON WEB TOKEN

Token 認證的來龍去脈

json web token是用來做什么的?

JSON Web Token - 在Web應用間安全地傳遞信息

八幅漫畫理解使用JSON Web Token設計單點登錄系統

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容