Koa鉴权

1,826 阅读2分钟

使用Cookie、Session实现鉴权

  1. 客户端登录,发送账户、密码给服务器
  2. 服务器查询数据库,验证账户与密码
  3. 验证正确,服务器向客户端发送Cookie同时,生成Session管理Cookie信息(一般使用Redis统一全局管理Session)
  4. 客户端会自动接收Cookie,并在此后每次请求都会自动在请求头附带Cookie
  5. 服务器根据Session校验Cookie的信息,判断是否需要登录或者未授权访问

下载需要的组件

npm i koa koa-session redis koa-redis co-redis koa-static koa-bodyparser -S

app.js

// 引入Koaconst Koa = require('koa');const app = new Koa();// 引入 koa-sessionconst session = require('koa-session');// 引入redisconst redis = require('redis');const redisStore = require('koa-redis');const redisClient = redis.createClient(6379,'localhost');// 转换redisconst wrapper = require('co-redis');const client = wrapper(redisClient);// 引入静态资源储量const static = require('koa-static');app.use(static(__dirname+'/public'));// 引入解析 koa 上下文(body)const bodyParser = require('koa-bodyparser');app.use(bodyParser())// 秘钥app.keys = ['some secret'];const SESS_CONFIG = {  key: 'kkkb:sess', // sessionKey   maxAge: 86400000, // 有效期  httpOnly: true, // Cookie在服务器有效(客户端无法通过js获取Cookie)  signed: true, // 是否签名  store: redisStore({client})}app.use(session(SESS_CONFIG,app));app.use(async (ctx, next) => {  if(ctx.path === '/favicon.ico') return;  // let n = await ctx.session.count || 0;  // ctx.session.count = ++n;  // ctx.body = '第' + n + '次访问';  //console.log(ctx.request.headers.cookie)  await redisClient.keys('*', async (err,keys) => {    // await console.log(keys);    keys.forEach(async key => {      redisClient.get(key, (err,val) => {        console.log(val);      })    })  })  await next();});const users = require('./routes/users');app.use(users.routes())app.listen(3000);

users.js

const Router = require('koa-router');const router = new Router({prefix: '/users'});router.post('/login', async ctx => {  const { body } = ctx.request;  // console.log('body',body);  ctx.session.userInfo = body.username;  ctx.body = {    ok: 1,    message: '登录成功'  };});router.get('/getUser', require('../middleware/auth'), async ctx => {  ctx.body = {    ok: 1,    message: '获取数据成功',    userInfo: ctx.session.userInfo  }})router.post('/logout', async ctx => {  delete ctx.session.userInfo;  ctx.body = {    ok: 1,    message: '登出系统'  };});module.exports = router;

auth.js

module.exports = async (ctx, next) => {  if(!ctx.session.userInfo){    ctx.body = {      ok: 0,      message: '用户未登录'    };  } else {    await next();  }}

使用token实现鉴权

  1. 客户端向服务器发送账户与密码
  2. 服务器查询数据库判断账户与密码正确性
  3. 服务器并向客户端发送令牌token
  4. 客户端收到token之后将其存储起来,放进Cookie或者LocalStorage
  5. 客户端每次向服务器请求资源会附带token
  6. 服务器验证token,验证通过则返回资源

下载相关中间件

npm i jsonwebtoken koa-jwt -S

使用jsonwebtoken加密

const jwt = require('jsonwebtoken');const jwtAuth = require('koa-jwt');const secret = 'it is a jwt secret'; // token加密秘钥router.post('/loginToken', async ctx => {  const { body } = ctx.request;  const userInfo = body.username;  ctx.body = {    message: '登录成功',    user: userInfo,    token: jwt.sign({      data: userInfo,      exp: Math.floor(Date.now() / 1000) + 60 * 60 // 一小时后过期    }, secret)  };});

客户端收到token使用LocalStorage存储

login: async function(){          const res = await axios.post('/users/loginToken', {            username: this.username,            password: this.password          })          localStorage.setItem('token', res.data.token);        }

客户端每次请求资源时将token附带在头部

axios.interceptors.request.use(config => {      const token = window.localStorage.getItem('token');      if(token){        config.headers.common['Authorization'] = 'Bearer '+token;      }      return config;    })

服务器验证token

router.get('/getUserToken', jwtAuth({secret}), async ctx => {  /**   * 通过jwtAuth验证之后,jwt会自动解析加密后data存入ctx.state里面   */  ctx.body = {    message: '获取数据成功',    userInfo: ctx.state.user.data  }})