koa2 使用passport权限认证

之前做的美团网项目,需要实现注册登录功能,项目地址:
https://github.com/xiongfeng555/mt-app
主要技术栈:Nuxt.js + Koa + MongoDB + Redis

本地用户登录,第三方登录都需要权限认证,权限认证的思路也极其简单,不外乎就是登录,登出,路由守护三部分。

今天要讲的权限认证中间件那就是:passport.js,passport目前包括多种登录策略,比如github登录,微信登录,Facebook登录,google等等。
官网:http://www.passportjs.org/docs/

本文参考以下博文整理发布:
https://www.cnblogs.com/lcxcsy/p/13819706.html

1.安装

koa2中使用的是 koa-passport 这个包。
本地验证用的是 passport-local这个策略

npm install -S koa-passport
npm install -S passport-local

2.配置

这里使用 passport-local 策略(本地权限认证)为例子。
因为passport使用之前要定义策略及序列化与反序列化操作,所以把 passport 的配置及策略写到一个文件passport.js。

// passport.js
import passport from 'koa-passport'
import LocalStrategy from 'passport-local'
import UserModel from '../../dbs/models/users'  //MongoDB数据库

// 新建策略
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, '用户不存在')
  }
}))

// 序列化ctx.login()触发
passport.serializeUser(function (user, done) {
  done(null, user)
})

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

export default passport

3.入口载入

然后在 koa 入口 app.js 中载入 passport.js 文件

import passport from './interface/utils/passport'

并在适当位置(看下边 app.js)使用passport中间件

app.use(passport.initialize())
app.use(passport.session())

4.后端路由编写

登录接口: POST/signin

router.post('/signin', async (ctx, next) => {
 // 调用passport配置的策略
  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)
})

登出接口:GET/exit

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

其他需要权限认证的接口

router.get('/getUser', async (ctx) => {
  //调用ctx.isAuthenticated()进行权限的认证
  if (ctx.isAuthenticated()) {
    const { username, email } = ctx.session.passport.user
    ctx.body = {
      user: username,
      email
    }
  } else {
    ctx.body = {
      user: '',
      email: ''
    }
  }
})

前端页面的接口请求

 login () {
      let self = this
      self.$axios
        .post('/users/signin', {
          username: window.encodeURIComponent(self.username),
          password: CryptoJS.MD5(self.password).toString()
        })
        .then(({ status, data }) => {
          if (status === 200) {
            if (data && data.code === 0) {
              location.href = '/'
            } else {
              self.error = data.msg
            }
          } else {
            self.error = `服务器出错`
          }
          setTimeout(function () {
            self.error = ''
          }, 1500)
        })
    }

到这里,本地权限认证基本完成了,post请求 /signin并且提交表单user,和 password即可登录一个用户。

5、总结
passport使用session来维护会话。对于token验证的来说,并不能用,所以要实现token验证的话还需要另外编写策略才行。

更多详细用法,请自行到官网查看文档。http://www.passportjs.org/docs/

上一篇有写到用验证码实现注册功能,这里贴一下链接:使用nodemailer实现发送邮件验证码
如果有不对的地方,欢迎批评指正!

posted @ 2021-04-11 15:18  前端小白狐  阅读(306)  评论(0)    收藏  举报