前言
在我之前的【Node服務集成權(quán)限認證中間件之Passport】一文中已經(jīng)介紹了如何為普通express應用集成passport認證中間件。那么對于下一代的Node應用框架——Koa,能否完美集成passport中間件呢?
困難
不得不承認,對于Koa而言,尤其是最新版本2.X版本Koa,其生態(tài)目前完全出于一個起步階段,對比目前express大量穩(wěn)定可用的中間件,的確是有許多的不足。但是開源的力量永遠是最強大的,只要有需求,就一定有解決方案
思路
1、首選,passport中間件的官方只是提供了對express的支持。但是相對應的,koa也有其對應的開源集成版本——【koa-passport】
2、這里需要注意的是,koa-passport本質(zhì)上并非全新實現(xiàn)的另外一個版本的passport,它僅僅只是作為中間件,將原先passport對express的支持,轉(zhuǎn)移到了koa上。通過分析其源碼可以看出,它其實是將原先綁定在express的req和res中的API方法,重新綁定到了koa的ctx中
3、美中不足的是koa-passport的官方文檔中并沒有給出很詳細的使用方法,其koa-passport-example項目的示例也沒有給出很清晰的使用說明,就我個人直接使用koa-passport-example項目,如果不加以修改,是無法完成認證功能的,所以難免會對初學者造成困擾,甚至是放棄
解決
對于koa-passport集成進入koa2版本,雖然是google和baidu了大量資料,但是很遺憾,目前似乎并沒有太多關(guān)于這兩者的集成文章,相關(guān)的都是比較老版本的文章或者是經(jīng)過實踐并沒有生效的文章,并沒有太多的參考價值
所以,這一篇文章可能是全網(wǎng)第一篇koa2版本正確集成koa-passport的教程,通過較長時間的分析koa-passport和passport的源碼,最終得出了以下的正確集成方法,在此作為文章分享出來
步驟
第一,安裝koa-passport
npm install koa-bodyparser --save
npm install passport --save
npm install passport-local --save
npm install koa-passport --save
npm install koa-session2 --save 【官方示例文檔上使用的是koa-session,存在兼容問題】
第二,創(chuàng)建passport配置文件passport_config.js
【UserModel是數(shù)據(jù)庫查詢封裝,在此省略】
const passport = require('koa-passport')
const LocalStrategy = require('passport-local')
const UserModel = require(__dirname + '/../../src/model/UserModel')
// 用戶名密碼驗證策略
passport.use(new LocalStrategy(
/**
* @param username 用戶輸入的用戶名
* @param password 用戶輸入的密碼
* @param done 驗證驗證完成后的回調(diào)函數(shù),由passport調(diào)用
*/
function (username, password, done) {
let where = { where: { username: username } }
UserModel.findOne(where).then(function (result) {
if (result != null) {
if (result.password == password) {
return done(null, result)
} else {
return done(null, false, '密碼錯誤')
}
} else {
return done(null, false, '未知用戶')
}
}).catch(function (err) {
log.error(err.message)
return done(null, false, { message: err.message })
})
}
))
// serializeUser 在用戶登錄驗證成功以后將會把用戶的數(shù)據(jù)存儲到 session 中
passport.serializeUser(function (user, done) {
done(null, user)
})
// deserializeUser 在每次請求的時候?qū)?session 中讀取用戶對象
passport.deserializeUser(function (user, done) {
return done(null, user)
})
module.exports = passport
第三,創(chuàng)建認證路由xauth.js
【這里使用的是koa-router的koa2版本】
// 路由相關(guān)
const Router = require('koa-router')
// 初始化路由
const router = new Router()
// 認證相關(guān)
const passport = require(__dirname + '/passport_config.js')
/**
* 認證登錄
*/
router.post('/xauth/login', function (ctx, next) {
return passport.authenticate('local', function (err, user, info, status) {
if (user) {
ctx.body = 'Y'
return ctx.login(user)
} else {
ctx.body = info
}
})(ctx, next)
})
/**
* 認證登出
*/
router.get('/xauth/logout', function (ctx, next) {
ctx.logout()
ctx.body = 'Y'
})
// 以下為自定義需要身份認證的路由
router.post('/xauth/test', function (ctx, next) {
if (ctx.isAuthenticated()) {
ctx.body = '認證通過'
} else {
ctx.throw(401)
ctx.body = '非法訪問'
}
})
module.exports = router
最后,Koa的App中初始化和引入passport
// 認證相關(guān)
const bodyParser = require('koa-bodyparser')
const mount = require('koa-mount')
const session = require("koa-session2")
const passport = require(__dirname + '/src/auth/passport_config.js')
const xauth = require(__dirname + '/src/auth/xauth.js')
// 初始化應用服務
const app = new Koa()
// 啟用認證路由
app.proxy = true
app.use(session({key: "SESSIONID"}))
app.use(bodyParser())
app.use(passport.initialize())
app.use(passport.session())
app.use(mount('/',xauth.routes()))
后記
關(guān)于本文中提到的內(nèi)容,引用于我的開源項目【XServer——組件化后端構(gòu)建】,本文代碼開源于Github的【x-koa——組件化后端開發(fā)模板】,十分感謝對于本文的閱讀,如有任何的疑問或者建議甚至批評,可以隨時通過評論或私信聯(lián)系我,我會第一時間回復