jwt在node中的應用與實踐
導語:由於http是無狀態的,請求響應過程中不儲存記錄使用者身份資訊,所以就出現了很多使用者識別儲存使用者身份的方法,比如cookie,session,jwt。我最近做的一個介面服務使用了jwt來儲存管理使用者資訊,相較於本地cookie儲存,伺服器端session儲存,jwt就變得比較安全和節省方便,本文就jwt在node服務中的使用方法做一個簡單的總結。
目錄
- jwt簡介
- 安裝配置
- 封裝方法
- 實戰練習
本文從以上四個方面介紹jwt的使用。
jwt簡介
概念
JWT全稱JSON Web Token,它是一種開放標準RFC 7519,定義了一種緊湊且自包含的方式,用於在各方之間作為JSON物件安全地傳輸資訊。JWT可以使用金鑰或使用RSA或ECDSA的公鑰/私鑰對進行簽名,可以對簽名進行驗證。
組成部分
jwt簽名令牌一般由三部分組成,分別是Header(頭部資訊),Payload(載荷),Signature(簽名),例如xxxxx.yyyyy.zzzzz
。
- header
一般是儲存令牌的型別和簽名演算法,比如:
{
"alg": "HS256",
"typ": "JWT"
}
- Payload
一般是儲存宣告,也就是使用者資訊和附件資料,分為註冊宣告、公共宣告和私人宣告。
比如:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
- 簽名
利用簽名演算法對Header和Payload進行簽名
比如:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
那麼一個標準的jwt簽名令牌會是這樣的eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
。
應用場景
- 使用者授權訪問
比如使用者登入後,服務端下發一個jwt令牌給客戶端,每次使用者請求資料都在請求頭裡面攜帶此令牌,服務端驗證通過後可以獲取到資料,這種方式開銷很小,並不需要服務端進行儲存,而且還可以跨域使用。
- 資訊交換
在各方之間儲存加密資訊,驗證簽名內容是否篡改。
安全性
由於令牌可以被拆解,裡面的header和Payload可以被解析看到,所以儘量不要在Payload裡面儲存一些私密的資訊。
安裝配置
下面就在node中使用jwt做一下操作。
在npm網站,有很多的jwt包,你可以選擇你認為合適的。
搜尋jwt
NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS
jwt | JSON Web Token for… | =mattrobenolt | 2012-05-05 | 0.2.0 |
express-jwt | JWT authentication… | =woloski… | 2021-08-11 | 6.1.0 | auth authn authentication authz authorization http jwt token oauth express
jsonwebtoken | JSON Web Token… | =dschenkelman… | 2019-03-18 | 8.5.1 | jwt
jwt-decode | Decode JWT tokens,… | =jeff.shuman… | 2020-11-16 | 3.1.2 | jwt browser
passport-jwt | Passport… | =themikenichol… | 2018-03-13 | 4.0.0 | Passport Strategy JSON Web Token JWT
koa-jwt | Koa middleware for… | =stiang… | 2021-09-24 | 4.0.3 | auth authn authentication authz authorization http jwt json middleware token oauth permissions koa
jsrsasign | opensource free… | =kjur | 2021-12-01 | 10.5.1 | crypto cryptography Cipher RSA ECDSA DSA RSAPSS PKCS#1 PKCS#5 PKCS#8 private key public key CSR PKCS#10 hash function HMac ASN.1 certexpress-jwt-permissions | Express middleware… | =angryunicorn… | 2021-08-18 | 1.3.6 | express middleware JWT permissions authorization token security
njwt | JWT Library for… | =robertjd | 2021-12-03 | 1.2.0 | jwt
fastify-jwt | JWT utils for… | =starptech… | 2021-12-03 | 4.1.0 | jwt json token jsonwebtoken fastify
did-jwt | Library for Signing… | =simonas-notcat… | 2021-12-03 | 5.12.1 |
hapi-auth-jwt2 | Hapi.js… | =nelsonic | 2020-09-08 | 10.2.0 | Hapi.js Authentication Auth JSON Web Tokens JWT
auth0-lock | Auth0 Lock | =jeff.shuman… | 2021-11-02 | 11.31.1 | auth0 auth openid authentication passwordless browser jwt
jwks-rsa | Library to retrieve… | =jeff.shuman… | 2021-10-15 | 2.0.5 | jwks rsa jwt
restify-jwt-community | JWT authentication… | =frbuceta | 2021-12-05 | 1.1.21 | auth authentication authorization http jwt token oauth restify
did-jwt-vc | Create and verify… | =simonas-notcat… | 2021-11-23 | 2.1.8 |
jwt-service | A simple wrapper… | =nfroidure | 2021-11-01 | 8.0.0 | jwt knifecycle
angular-jwt | Library to help you… | =jeff.shuman… | 2019-03-20 | 0.1.11 |
@thream/socketio-jwt | Authenticate… | =divlo | 2021-07-23 | 2.1.1 | socket socket.io jwt
appstore-connect-jwt-gene | [![NPM](https://nod… | =poad | 2021-10-15 | 1.0.1 | jwt appstore
rator-core |
安裝jwt
我個人覺得這個jsonwebtoken很不錯,本文就使用這個包。
npm i jsonwebtoken
常見用法
- 簽名
簽名語法:jwt.sign(payload, secretOrPrivateKey, [options, callback])
。
例如:
// 一般簽名
var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'secret');
// 加私鑰簽名
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256'});
// 設定過期時間
jwt.sign({
data: 'bar'
}, 'secret', { expiresIn: 60 * 60 }); // 1h
- 驗證
驗證語法:jwt.verify(token, secretOrPublicKey, [options, callback])
例如:
// 一般驗證
var decoded = jwt.verify(token, 'secret');
console.log(decoded.foo) // bar
// 公鑰驗證
var cert = fs.readFileSync('public.pem');
jwt.verify(token, cert, function(err, decoded) {
console.log(decoded.foo) // bar
});
- 解碼
解碼語法:jwt.decode(token [, options])
例如:
var decoded = jwt.decode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload);
封裝方法
根據安裝配置裡面的方法,可以根據自己的需要進行二次封裝,更加適合自己的方法。
- 引入依賴包和配置
const jwt = require("jsonwebtoken");
const config = {
secret: '2021123456**',
time: 60 * 60,
}
- 簽名
function create (data, time) {
let token = jwt.sign(data, config.secret, {
algorithm: "HS256",
expiresIn: time || config.time,
})
return token;
}
- 驗證
function verify (token) {
return jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
return {
code: 1,
msg: 'invalid',
data: null,
}
} else {
return {
code: 2,
msg: 'valid',
data: decoded,
}
}
})
}
- 解碼
function decoded (token, complete = true) {
return jwt.decode(token, {
complete,
});
}
上面是比較簡單的方法,如果你還想使用公鑰私鑰,可以用上面安裝配置裡面介紹的那樣。
實戰練習
經過上面的封裝方法,可以來實戰演練一下,是否有效。
- 新建一個資料夾
test
,新建一個檔案index.js
用於存放測試案例,jwt.js
用於儲存呼叫方法。
mkdir test
cd test
npm init -y
npm i jsonwebtoken
- jwt方法
// jwt.js
const jwt = require('jsonwebtoken');
const config = {
secret: '2021123456', // 金鑰
time: 60*60, // 過期時間
}
// 建立簽名令牌
function create (data, time) {
let token = jwt.sign(data, config.secret, {
algorithm: 'HS256',
expiresIn: time || config.time,
});
return token;
}
// 驗證令牌
function verify (token) {
return jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
return {
code: 1,
msg: 'invalid',
data: null,
}
} else {
return {
code: 2,
msg: 'valid',
data: decoded,
}
}
})
}
// 解碼令牌
function decoded (token, complete = true) {
return jwt.decode(token, {
complete,
});
}
const token = {
create,
verify,
decoded,
}
module.exports = token;
- 建立token,驗證token,解碼token
// index.js
const jwt = require('./jwt');
// 生成令牌
let token = jwt.create({'id': 1, 'name': 'mark'}, 60*60*2);
console.log(token);
/*
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpZCI6MSwibmFtZSI6Im1hcmsiLCJpYXQiOjE2MzkxMDYyNzMsImV4cCI6MTYzOTExMzQ3M30.
20O1r0NVMf-j-9RwNcgls9ja0n1rGqSKN51_cRcvpE8
*/
// 驗證令牌
let verifyRes = jwt.verify(token);
console.log(verifyRes);
/*
{
code: 2,
msg: 'valid',
data: { id: 1, name: 'mark', iat: 1639106273, exp: 1639113473 }
}
*/
// 解碼令牌
let deRes = jwt.decoded(token, true);
console.log(deRes);
/*
{
header: { alg: 'HS256', typ: 'JWT' },
payload: { id: 1, name: 'mark', iat: 1639106273, exp: 1639113473 },
signature: '20O1r0NVMf-j-9RwNcgls9ja0n1rGqSKN51_cRcvpE8'
}
*/
執行一下命令node index.js
測試是否正確。
好了,以上就是jwt在node中的一些應用和實踐方法!