01月06, 2019

passport模块在koa中的使用

前阵子,技术群里面的哥们发了一个链接:meituan-app。今天闲来无事,研究了一下。

那个README感觉有所欠缺,需要打开mongod以及redis的服务才能跑。

在看代码的过程中,发现一个新大陆:passport。查了一下相关资料,它是一个权限认证中间件,能够把登陆认证和应用程序分离出来,从而保证了更清晰的代码结构。

在网上也找到两篇学习资料:

其实代码还是比较容易的。登录认证写了一个文件,然后应用程序去引用那个登录认证的文件即可。

// passport.js
import passport from 'koa-passport'
import LocalStrategy from 'passport-local'
import UserModel from 'dbs/models/users'

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, '用户不存在')
  }
}))

// 序列化对象
passport.serializeUser(function(user, done){
  done(null, user)
})

// 反序列化对象
passport.deserializeUser(function(user, done) {
  return done(null, user)
})

export default passport

koa的入口文件导入这个passport

import Koa from 'koa'
import passport from './passport'
import session from 'koa-generic-session'
import Redis from 'koa-redis'

const app = new Koa()
app.keys= ['mt', 'keyskeys']
app.proxy = true
app.use(session({
  key: 'mt',
  prefix: 'mt:uid',
  store: new Redis()
}))
app.use(passport.initialize())
app.use(passport.session())

我们通过app.use来加载passport的initializesession方法,然后ctx上下文对象就拥有了loginloginout方法,这两个分别在登录和登出的时候使用。

// 业务代码 登录
import Passport from './passport'

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) {
        ctx.body = {
          code: 0,
          msg: '登录成功',
          user
        }
        return ctx.login(user)
      } else {
        ctx.body = {
          code: 1,
          msg:info
        }
      }
    }
  })(ctx, next)
})

ctx.login方法被调用时,就会执行在passport.js里面的触发序列化操作serializeUser

(反序列化是在在请求时,session中如果存在 "passport":{"user":"xxx"}时会触发定义的反序列化操作。)

// 业务代码登出
router.get('/exit', async(ctx, next) => {
  await ctx.logout()
  if (!ctx.isAuthenticated()) {
    ctx.body = {
      code: 0
    }
  } else {
    ctx.body = {
      code: -1
    }
  }
})

个人感觉这样的代码可阅读性确实提高了不少。在npm里面,今天还看到了l-passport,似乎挺强大的,改天试试。

本文链接:www.my-fe.pub/post/passport-use-in-koa.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。