1、注册

1.1生成token

安装 npm jsonwebtoken

  1. config.jwt = {
  2. secret: 'a6e8561e-58df-4715-aa21-b5d1a091e71a',
  3. expiresIn: '1d'
  4. }
  1. const jwt = require('jsonwebtoken');
  2. createToken(data) {
  3. const token = jwt.sign(data, this.app.config.jwt.secret, {
  4. expiresIn: this.app.config.jwt.expiresIn
  5. })
  6. return token
  7. }

1.2 自动验证token

利用中间件 进行token验证, 并将登录用户信息存储到ctx中, 供后续中间件使用

  1. module.exports = (options = { required: true }) => {
  2. return async (ctx, next) => {
  3. // 1. 获取请求头中的 token 数据
  4. let token = ctx.headers.authorization
  5. token = token
  6. ? token.split('Bearer ')[1] // Bearer空格token数据
  7. : null
  8. if (token) {
  9. try {
  10. // 3. token 有效,根据 userId 获取用户数据挂载到 ctx 对象中给后续中间件使用
  11. const data = ctx.service.user.verifyToken(token)
  12. ctx.user = await ctx.model.User.findById(data.userId)
  13. } catch (err) {
  14. ctx.throw(401)
  15. }
  16. } else if (options.required) {
  17. ctx.throw(401)
  18. }
  19. // 4. next 执行后续中间件
  20. await next()
  21. }
  22. }
  1. // 引入 auth , 在需要token 验证的接口里 写入auth
  2. 'use strict';
  3. /**
  4. * @param {Egg.Application} app - egg application
  5. */
  6. module.exports = app => {
  7. const { router, controller } = app;
  8. const auth = app.middleware.auth()
  9. router.prefix('/api/v1') // 设置基础路径
  10. router.post('/create', controller.user.create);
  11. router.post('/users/login', controller.user.login);
  12. router.get('/user', auth, controller.user.getCurrentUser);
  13. };

1.3 密码加密

安装 npm crypto

  1. const crypto = require('crypto')
  2. const _ = require('lodash')
  3. exports.md5 = str => {
  4. return crypto.createHash('md5').update(str).digest('hex')
  5. }
  6. exports._ = _

data.password = this.ctx.helper.md5(data.password)

2、表单验证

安装 npm egg-validate

  1. exports.validate = {
  2. enable: true,
  3. package: 'egg-validate'
  4. }

3、配置异统一异常处理

  • https://eggjs.org/zh-cn/core/error-handling.html
  • https://eggjs.org/zh-cn/basics/middleware.html ```typescript module.exports = () => { // 外层函数负责接收参数 // 返回一个中间件处理函数 return async function errorHandler (ctx, next) { try {

    1. await next()

    } catch (err) {

    1. // 所有的异常都在 app 上触发一个 error 事件,框架会记录一条错误日志
    2. ctx.app.emit('error', err, ctx)
    3. const status = err.status || 500
    4. // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
    5. const error =
    6. status === 500 && ctx.app.config.env === 'prod'
    7. ? 'Internal Server Error'
    8. : err.message
    9. // 从 error 对象上读出各个属性,设置到响应中
    10. ctx.body = { error }
    11. if (status === 422) {
    12. ctx.body.detail = err.errors
    13. }
    14. ctx.status = status

    } } }

  1. ```typescript
  2. config.middleware = ['errorHandler']
  1. 1
  2. this.ctx.validate({
  3. username: { type: 'string' },
  4. email: { type: 'email' },
  5. password: { type: 'string' },
  6. });
  7. 2
  8. this.ctx.throw(422, 'validation Failed', {
  9. errors: [
  10. {
  11. code: 'invalid',
  12. field: 'email',
  13. message: 'has already exists',
  14. },
  15. ],
  16. });