Koa & Mongoose & Vue实现先后端分离--07登陆加密&服务端参数校验

上节回顾

  • Elementscssaxios的使用
  • 路由定义与跳转
  • 登陆&注册客户端逻辑

工做内容

  • crypto-js加密
  • 服务端参数校验

准备工做

  • npm i -S crypto-js // 先切换到/client目录下
  • npm install -S koa-bouncer // 先切换到/server目录下

更新逻辑

前端加密

上几节保存的密码都是明文的,这里借助crypto-js加密密码。css

// 更新文:client/src/views/login/index.vue
...
import md5 from 'crypto-js/md5'
...
const res = await http.post(
'/users?action=login',
{
  account,
  password: md5(password).toString()
}
)
...
const res = await http.post(
'/users?action=register',
{
  account,
  password: md5(password).toString()
}
)
...

在请求登陆 & 注册接口传参时,进行加密。
测试结果
md5
动态测试结果
register.gif前端

后端校验

在前端表单提交中,有校验逻辑:
validation
但是,经过Postman/其它方式请求接口时,不会走这些校验,因此,后端校验是很必要的。vue

不借助库校验

不借助第三方包的话,就自定义一个中间件(这里举特例)ios

// 新建文件:server/validation/user.js
const validate = (ctx, next) => {
  const { account, password } = ctx.request.body;
  // account: [
  //   { required: true, message: '请输入账号', trigger: 'blur' },
  //   { min: 5, message: '长度至少5个字符', trigger: 'blur' }
  // ],
  // password: [
  //   { required: true, message: '请输入密码', trigger: 'blur' },
  //   { min: 3, message: '长度至少3个字符', trigger: 'blur' }
  // ]
  if (!account || !password) {
    ctx.body = {
      code: '403',
      data: null,
      msg: '账号/密码不能为空'
    }
    return;
  }
  if (account.trim().length < 5) {
    ctx.body = {
      code: '403',
      data: null,
      msg: '账号长度至少5个字符'
    }
    return;
  }
  next()
}

module.exports = {
  validate
}
// 更新文件:server/router/users.js
...
const { validate } = require('../validation/user'); //新增
...
  {
    path: '/',
    method: 'POST',
    handle: async (ctx) => {
        ...
    },
    middlewares: [
      validate //新增
    ]
  },
...
//更新文件:server/utils/router.js
function register(routes) {
  routes.forEach((route, idx) => {
    const { path, method, middlewares = [], handle } = route; // 加入middlewares
    this[method.toLowerCase()](path, ...middlewares, async (ctx, next) => {
      await handle(ctx);
    })
  })
}
module.exports = {
  register,
}

使用koa-bouncer校验

和‘不借助库校验’二选一,使用该方法时,注意还原‘不借助库校验’的代码。git

// 更新文件:server/app.js
...
const bouncer = require('koa-bouncer'); //新增
const routes = require('./router');

const app = new koa();
app.use(cors());
app.use(bouncer.middleware()); //新增
// 中间件的错误处理
app.use(function(ctx, next){//新增
    console.log(err)
    if (err.name === 'ValidationError') { //bouncer校验失败会抛出错误,根据错误类型做出相应处理
      ctx.body = {
        code: '403',
        data: null,
        msg: err.message
      }
    }
  });
});
...

bouncer校验失败会抛出错误,根据错误类型做出相应处理github

// 更新文件:server/router/users.js
...
const validate = async (ctx, next) => {
  ctx.validateBody('account')
    .required('账号必填')
    .isString('账号必须是字符串')
    .trim()
    .tap(x => x.length)
    .gte(4, '账号长度至少为5个字符')
  ctx.validateBody('password')
    .required('密码必填')
    .isString('密码必须是字符串')
    .trim()
  await next(); // 这里必须是async/await形式,不然,如动态图,没有返回值。
}
...

  {
    path: '/',
    method: 'POST',
    handle: async (ctx) => {
      const { action } = ctx.query;
      switch (action) {
        case 'register':
          await register(ctx);
          break;
        case 'login':
          await login(ctx);
          break;
        default:
          await list(ctx);
      }
    },
    middlewares: [
      validate // 新增
    ]
  },
...
//更新文件:server/utils/router.js
function register(routes) {
  routes.forEach((route, idx) => {
    const { path, method, middlewares = [], handle } = route; // 加入middlewares
    this[method.toLowerCase()](path, ...middlewares, async (ctx, next) => {
      await handle(ctx);
    })
  })
}
module.exports = {
  register,
}

测试结果
bouncer
动态测试结果
koa-bouncer.gifnpm

参考文档

crypto-js
koa-bounceraxios

相关文章
相关标签/搜索