Koa初體驗之RSA256+jsonwebtoken的JWT
項目介紹
使用RSA256加密實現jwt鑑權最終獲取token
項目開始
1.安裝依賴
npm install jsonwebtoken
2.獲取RSA公鑰和私鑰
(因系統不同命令有所不同 ,我這邊是mac栗子)
openssl
genrsa -out rsa_private_key.pem 1024
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
完成後生成兩個文件(rsa_private_key.pem 與 rsa_public_key.pem)
當然這塊也可以修改文件名,我修改成了我喜歡的 ,並統一放到了文件夾下,如圖所示:
代碼實現
1.設置登錄的路由
koa.use(koaRoute.post('/sessions', controller.post.bind(controller)))
2.Controller層SessionsController.js
//登錄post接口
post (ctx) {
//首先判斷headers不能爲空
if (ctx.headers.authorization === undefined || ctx.headers.authorization === null || ctx.headers.authorization === '') {
ctx.throw(400, 'Authorization header must be provided!')
} else {
return this._handleAuthorization(ctx)
}
}
_handleAuthorization (ctx) {
const [type] = ctx.headers.authorization.split(' ')
if (type.toLowerCase() === 'basic') {
return this._handleBasicAuthentication(ctx)
} else {
ctx.throw(400, 'Invalid authentication type!')
}
}
_handleBasicAuthentication (ctx) {
const [, base64String] = ctx.headers.authorization.split(' ')
console.log(base64String)
const [username, password] = Buffer.from(base64String, 'base64').toString().split(':')
console.log(username + password)
return this.getUserByCredentials(username, password)
.then(user => this._handleUser(ctx, user))
.then(jwt => this._respondWithJwt(ctx, jwt))
}
async getUserByCredentials (username, password) {
//密碼加密
const passwordHash = crypto.createHash('sha256')
.update(password)
.digest('hex')
console.log(passwordHash)
const user = await this._getUserByUsername(username)
console.log(user)
if (user === null) {
return null
} else {
if (user.passwordHash === passwordHash) {
return user
} else {
return null
}
}
}
_getUserByUsername (username) {
//查詢user表用戶名和傳入的用戶名是否一樣
return this._User.findOne({
where: { userName: username }
})
}
_handleUser (ctx, user) {
if (user === null) {
ctx.throw(400, 'Invalid user!')
} else {
const payload = {
usr: user.id,
role: user.role,
name: user.name
}
console.log(payload)
return this._generateJwt(payload)
}
}
// jwt.sign(payload, secretOrPrivateKey, [options, callback])
// 第一個是token載體,放一些需要存放在token裏的內容,我這裏希望token傳遞userId,role,name
// 第二個是密鑰,可以簡單的輸入string作爲密鑰,也可以採用加密算法,例如我現在用的RSA256
// 第三個是option,因爲jsonwebtoken加密方式默認是RS256,所以如果用其他加密方式需要在option的algorithm中進行申明,以及其他一些參數
_generateJwt (payload) {
const minutes = 432000
const privateKey = fs.readFileSync('rsaKeys/jwtRS256.key')
const options = { algorithm: 'RS256', expiresIn: minutes * 60 }
return jwt.sign(payload, privateKey, options)
}
_respondWithJwt (ctx, jwt) {
ctx.status = 201
ctx.body = jwt
return ctx
}
}
3.入口文件引入(app.js)
const jwt = require('koa-jwt')
const fs = require("fs")
const publicKey = fs.readFileSync('./rsaKeys/jwtRS256.key.pub')//引用公鑰
app.use(jwt({
secret: publicKey,
key:'token'
}).unless({
path: ['/sessions']
}));
測試登錄接口
1.插件測試登錄接口,返回token
我這裏用的是谷歌自帶的插件測試接口
headers 裏Authorization輸入登錄的用戶名密碼
設置這裏就結束裏 觸發send按鈕 就返回得到token
2.測試其他接口加上token訪問
不帶token,接口返回結果如圖(401)
帶token接口返回結果如圖