搭建日记(二):通用CRUD接口+登录实现+路由守卫

通用CRUD接口

server端创建查找模块中间件
server/middleware/resource.js

module.exports = options => {
  return async (req, res, next) => {
    const modelName = req.params.resource
    req.Model = require(`../models/${modelName}`)
    console.log('modelName',modelName)
    next()
  }
}
model/user-admin.js 建数据模型
const mongoose = require('mongoose')
const schema = new mongoose.Schema({
    username:{
        type:String,
        required: true,
    },
    role:{
        type:String,
        required: true,
    },
    password:{
        type:String,
        select:false,//防止查询出密码
        set(val) { //密码加密存储
            return require('bcrypt').hashSync(val, 10)
        }
    },
})
module.exports = mongoose.model('user-admin',schema)
route/admin/index.js 接口文件引入
//合并URL参数,将父级的参数合并到router里面
    const router = express.Router({
        mergeParams: true
    })

// 通用件接口改造

    // 创建资源
    router.post('/', async (req, res) => {
        const model = await req.Model.create(req.body)
        res.send(model)
    })
    // 更新资源
    router.put('/:id', async (req, res) => {
        const model = await req.Model.findByIdAndUpdate(req.params.id, req.body)
        res.send(model)
    })
    // 删除资源
    router.delete('/:id', async (req, res) => {
        await req.Model.findByIdAndDelete(req.params.id)
        res.send({
            success: true
        })
    })
    // 资源列表 - 分页
    router.get('/', async (req, res) => {
        const queryOptions = {}
        if (req.Model.modelName === 'route') {
            queryOptions.populate = 'parentId'
        }
        const items = await req.Model.find().setOptions(queryOptions).limit(100)
        console.log('items',items)
        res.send(items)
    })

    // 资源详情
    router.get('/:id', async (req, res) => {
        const model = await req.Model.findById(req.params.id)
        console.log('model',model)
        res.send(model)
    })


 // 调用通用接口中间件

    const resourceMiddleware = require('../../middleware/resource')
    app.use('/admin/api/rest/:resource', resourceMiddleware(), router)
    // 路径,中间件,回调函数

 // 统一异常处理
    app.use( async (err,req,res,next) => {
        res.status(err.statusCode || 500).send({
            message: err.message
        })
    })
admin前端新增用户编辑页面
......html....
接口调用带rest前缀=>后端通用校验
 
async save(){
      let res
      if (this.id) {
        res = await this.$http.put(`/rest/user-admin/${this.id}`, this.userForm)
      } else {
        res = await this.$http.post('/rest/user-admin', this.userForm)
      }
      console.log('res',res)
      this.$router.push('/user/list')
      this.$message({
        type: 'success',
        message: '保存成功'
      })
    },
    async fetch(){
      const res = await this.$http.get(`/rest/user-admin/${this.id}`)
      this.model = res.data
    },
路由文件router/index.js 添加路径 ,路由文件挂在main.js中
import Main from '../views/Main'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Main',
    component: Main,
    meta: { title:'系统管理' },
    children:[
      {
        path:'/route',
        meta: { title:'系统管理' },
        component: () => import('@/views/route')
      },
      {
        path:'/user/list',
        meta: { title:'用户管理' },
        component: () => import('@/views/user/List')
      },
      {
        path:'/user/edit',
        meta: { title:'用户编辑' },
        component: () => import('@/views/user/Edit')
      }
    ]
  },
]

const router = new VueRouter({
  base: process.env.BASE_URL,
  routes
})

export default router

登录实现 - 先添加一个用户再加登录token!!!!

server端添加登录校验中间件auth.js
module.exports = options => {
  // 断言库 if false  => ()
  const assert = require('http-assert')
  const config =require('../config')
  const jwt = require('jsonwebtoken')
  /*const userAdmin = require('../models/user-admin')*/

  return async (req, res, next) => {
    const token = String(req.headers.authorization || '').split(' ').pop()
    // token 为false =》 401 提示
    assert(token, 401, '请先登录')
    const { id } = jwt.verify(token, config.secretKey)
    // id 为false =》 401 提示
    assert(id, 401, '请先登录')
    await next()
  }
}
router/admin/index.js 应用,加登录接口
    const assert = require('http-assert')
    const jwt = require('jsonwebtoken')
    
    // 登录调用modelB不走通用
    const userAdmin = require('../../models/user-admin')

    // token 校验中间件
    const authMiddleware =require('../../middleware/auth')
    app.use('/admin/api/rest/:resource', authMiddleware(),resourceMiddleware(), router)
    // 路径,中间件,回调函数

    // 登录接口
    app.post('/admin/api/login', async (req, res) => {
        // 结构赋值
        const { username, password } = req.body

        // 1.根据用户名找用户,引入模型,定义方法
        const user = await userAdmin.findOne({ username 
}).select('+password').select('+role')
        assert(user ,422,'该用户不存在')

        // 2.校验密码
        // 比较密码,返回布尔值.数据表密码设置select为false不可读取,此时需要强制取出密码 findOne.select('+item')
        const isValid = require('bcryptjs').compareSync(password, user.password)
        assert(isValid ,422,'密码错误')

        // 3.返回token,如果是错误,则在http.js中拦截器统一处理
        // 设置secretOrPrivateKey !!!!!
        const config =require('../../config')
        const token = jwt.sign({ id: user.id },config.secretKey, {expiresIn: 1800000})
        res.send({ code: 20000, message: 'ok', data: { token:token,username:username,role:user.role } })
    })
config.js -> 根目录建,变量配置
module.exports = {
    secretKey: 'fys-NO-ONE',
    mongoUrl: 'mongodb://localhost:27017/fys-project'
}

admin前端修改

路由文件添加拦截
router.beforeEach((to, from ,next) => {
  if (!to.meta.isPublic && !localStorage.token) {
    return next('/login')
  }
  next()
})
请求拦截改造
// 请求拦截配置
http.interceptors.request.use(function (config) {
    // token识别
    console.log('localStorage.token',localStorage.token)
    if (localStorage.token) {
        config.headers.Authorization = 'Bearer ' + localStorage.token
    }
    return config;
}, function (error) {
    return Promise.reject(error);
})
// 响应
http.interceptors.response.use(res => {
    return res.data
}, err => {
    if (err.response.data.message) {
        Vue.prototype.$message({
            type: 'error',
            message: err.response.data.message
        })

        if (err.response.status === 401) {
            router.push('/Login')
        }
    }

    return Promise.reject(err)
})
 登录.vue 调用
 async login() {
      const res = await this.$http.post('login', this.loginForm)
      console.log('res',res)
      localStorage.token = res.data.token
      localStorage.username = res.data.username
      localStorage.role = res.data.role
      this.$router.push('/')
      this.$message({
        type: 'success',
        message: '登录成功'
      })
    },

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值