koa-passport
是koa
的一个中间件,它实际上只是对passport
的一个封装。利用koa-passport
可以简便的实现登录注册功能,不但包括本地验证,还有很多提供第三方登录的模块可以使用。这篇博客只讲一下登陆验证这块的一些简单内容
安装依赖
npm install -S koa-passport
npm install -S passport-local
引包
import passport from 'koa-passport'
import LocalStrategy from 'passport-local'
import UserModel from '../../dbs/models/users'
配置验证策略
koa-passport默认使用username
和password
做验证
passport.use(new LocalStrategy(async function(username, password, done) {
let where = {
username
};
//在数据库中寻找输入的用户信息
let result = await UserModel.findOne(where)
if (result != null) {
if (result.password === password) {
return done(null, result)
} else {
return done(null, false, '密码错误')
}
} else {
return done(null, false, '用户不存在')
}
}))
序列化
在用户登陆验证成功后将会把用户的数据储存到session
中,在调用 ctx.login()
时会触发序列化操作,把用户对象存到 session
里。
passport.serializeUser(function(user, done) {
done(null, user)
})
反序列化
每次请求将从session
中读取用户对象,session
中如果存在 "passport":{"user":"xxx"}
时会触发定义的反序列化操作
passport.deserializeUser(function(user, done) {
return done(null, user)
})
别忘了export default passport
导出配置好的模块
import Koa from 'koa'
import session from 'koa-generic-session'
import Redis from 'koa-redis'
import passport from './interface/utils/passport'
const app = new Koa()
// session的加密处理
app.keys = ['mt', 'keyskeys']
app.use(session({
key: 'mt',
prefix: 'mt:uid',
store: new Redis()
}))
//initialzie()函数的作用是为上下文添加passport字段, 会在ctx挂载以下方法
//ctx.state.user 认证用户
//ctx.login(user) 登录用户
//ctx.logout() 用户退出登录
//ctx.isAuthenticated() 判断是否认证
app.use(passport.initialize())
//开启koa-passport对session的支持,passport.session()是使passport能够从session中提取用户信息
app.use(passport.session())
router.post('/signin', async(ctx, next) => {
return Passport.authenticate('local', function(err, user, info, status) {
if (err) {
ctx.body = {
code: -1,
msg: err
}
} else {
if (user) {
//user是我们在数据库中找到的数据
ctx.body = {
code: 0,
msg: '登录成功',
user
}
//可以存储用户的session
return ctx.login(user)
} else {
ctx.body = {
code: 1,
//info是在验证里面判断后的信息,密码错误或者用户不存在
msg: info
}
}
}
})(ctx, next)
})
router.get('/getUser', async(ctx) => {
if (ctx.isAuthenticated()) {
// 策略通过done将user存储到了session中, 并将sessionID写入到客户端的cookie上,
//将用户信息附加到请求对象req.session.passport.user上
const { username, email } = ctx.session.passport.user
ctx.body = {
user: username,
email
}
} else {
ctx.body = {
user: '',
email: ''
}
}
})
router.get('/exit', async(ctx, next) => {
//logout方法可以删除用户的session,不带参数
await ctx.logout()
if (!ctx.isAuthenticated()) {
ctx.body = {
code: 0
}
} else {
ctx.body = {
code: -1
}
}
})