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

相關文章
相關標籤/搜索