vue+egg+mongoDB全栈项目
一、使用的框架
vue的vue2技术栈
node的egg框架
robo3T软件mongoDB数据库\
二、vue的搭建
参考www.jianshu.com/p/8105d6c16…\
1.安装@vue/cli
cnpm install -g @vue/cli(mac 下 sudo)
2.用vue视图来配置项目
(1)vue ui
输入项目文件夹(vue_front) ,手动配置,如下图
(2)启动项目
npm i
npm run serve
如果测试组件 npm run test:unit
3.http使用
npm i axios -D
vue.config.js文件添加
module.exports = { devServer: { proxy: { // 配置跨域处理 可以设置多个 "/api": { target: "http://127.0.0.1:7001/", //跨域请求头信息 changeOrigin: true, ws: false, secure: false, // 如果是https接口,需要配置这个参数 pathRewrite: { "^/api": "", }, }, }, }, };
main.js文件
import http from "./plugins/http"; Vue.use(http);
http.js文件
import Vue from "vue"; import axios from "axios"; // 负责axios的各种配置,前缀,token管理,路由跳转 let service = axios.create({ timeout: 5000, baseURL: "/api", }); export default ({ store, redirect }) => { console.log("store, redirect", store, redirect); service.interceptors.request.use( (config) => { const token = window.localStorage.getItem("token"); if (token) { config.headers.common["Authorization"] = "Bearer " + token; } console.log("config---------------1", config); return config; }, (err) => { console.log("err", err); return Promise.reject(err); } ); // 响应拦截器 service.interceptors.response.use( async (response) => { console.log("response---------------1", response); let { data } = response; if (data.code == 0) { } else if (data.code == -666) { } return data; }, (error) => { // 错误处理统一格式 console.log("error", error); alert("服务器挂了,请联系管理员") // return Promise.resolve({ // result: false, // status: "fail", // code: -1, // msg: "网络连接不稳定,请检查网络情况", // data: error, // }); } ); }; Vue.prototype.$http = service; export const http = service;
4.添加login和home
在App.vue文件
router
import Vue from "vue"; import VueRouter from "vue-router"; Vue.use(VueRouter); // ["push", "replace"].forEach((method) => { // const originalCall = VueRouter.prototype[method]; // VueRouter.prototype[method] = function error(location, onResolve, onReject) { // if (onResolve || onReject) { // return originalCall.call(this, location, onResolve, onReject); // } // return originalCall.call(this, location).catch((err) => err); // }; // }); const router = new VueRouter({ mode: "history", // base: import.meta.env.BASE_URL, routes: [ { path: "/", name: "index", component: () => import("@/views/home/index.vue"), }, { path: "/login", name: "login", component: () => import("@/views/account/login.vue"), }, ], }); router.onError((error) => { console.log(error) // if (import.meta.env.DEV) { // console.error(error); // return; // } // const pattern = /Loading .* failed/g; // const isChunkLoadFailed = error.message.match(pattern); // const targetPath = router.history.pending.fullPath; // if (!isChunkLoadFailed) return error; // window.location.href = `/${import.meta.env.BASE_URL}${targetPath}`; }); export default router;
5.Vue 设置全局Css变量在vue.config.js
css: { loaderOptions: { sass: { prependData: '@import "~@/styles/varibale.scss";' } } },
6.路径
js import login from "@/images/login.png";
css background: url("~@/images/login.png") center no-repeat;
7.icon使用
新建项目,然后在官方组件库可添加图标到购物车🛒,然后从购物车添加到项目
8.cnpm i md5 加盐加密密码
password: md5(this.model.password), 数据库设计都喜欢用单向加密的方式保存密码,验证时对提交的密码再次加密之后做密文对比
前台项目,后台项目都需要加 先前台md5加密传给后台比如md5(pass),然后后台在加上一个自己的md5(password+HashSalt) 在加密一遍。用户登录查询时也加上自己HashSalt查询就可以实现2重加密。这样想盗用,要有用户密码和HashSalt才可以。
md5是单向加密,理论上不可解密。彩虹表出现了可以解密,所以要使用加盐再次加密。
9.前端使用post请求会报错invalid csrf token
let result = await this.$http.post("/user/register", obj);
egg后台:
router.post('/user/register',controller.user.register)
csrf Egg 安全机制 CSRF 的防范
在config文件下config.default.js添加
security:{ csrf:{ enable:false } },
配置 ,跳过 crsf 检测
三、egg的搭建
1.项目启动
npm i -g egg-init(sudo npm i -g egg-init)
egg-init egg-back --type=simple. (egg-back. 项目名)
cd egg-back
cnpm i
npm run dev 在localhost:7001端口打开应用
2.验证码添加
cnpm i svg-captcha -D
app文件->controller文件下添加
base.js做成功,失败数据返回格式
const Controller = require('egg').Controller; // controller的父类, 提供公用方法 class BaseController extends Controller { // 提供成功数据的 success(data){ this.ctx.body = { code:0, data } } // 提供成功消息 message(msg){ this.ctx.body ={ code:0, message:msg } } error(msg, code=-1){ this.ctx.body = { code, message:msg } } } module.exports = BaseController;
用户登录注册数据 user.js
'use strict'; // const md5 = require('md5') const BaseController = require('./base'); class UserController extends BaseController { async captcha(){ // controller只写业务逻辑,公用的功能,抽象成service, // 生成验证码,放在service李最好 const {ctx} = this const captcha = this.service.tools.captcha() console.log('图片验证码',captcha.text) ctx.session.captcha = captcha.text ctx.response.type = 'image/svg+xml' ctx.body = captcha.data } } module.exports = UserController;
app.文件-》添加service文件->tools.js添加
const Service = require('egg').Service const svgCaptcha = require('svg-captcha') class ToolsService extends Service{ captcha(){ let capt = svgCaptcha.create({ size:4, fontSize:50, width:100, height:40, noise:3 }) return capt } } module.exports = ToolsService
cnpm i egg-jwt --save
cnpm i egg-mongoose --save
cnpm i marked --save
3.数据库连接
mac终端打开输入 cd /usr/local/MongoDB
启动:mongod --dbpath data --logpath log/mongod.log --logappend --fork
后台。cnpm i egg-mongoose -S
在config文件下config.default.js添加
mongoose:{ // 链接地址 client:{ url: 'mongodb://127.0.0.1:27017/eggDatabase', options:{} } },
在config文件下plugin.js添加
exports.mongoose = { enalbe:true, package:'egg-mongoose' }
在app里面的controller里的user.js添加checkEmail,register
async checkEmail(email){ const user = await this.ctx.model.User.findOne({email}) return user } async register(){ const {ctx} = this const {captcha,email, password,nickname} =ctx.request.body console.log('registerregisterregisterregister',ctx.request.body) if(captcha.toUpperCase() == ctx.session.captcha.toUpperCase()){ // // 新增用户 // // mongodb里面新增数据 // // 邮箱和昵称不能重复的 if(await this.checkEmail(email)){ return this.success('邮箱重复了') } let ret = await ctx.model.User.create({ username, // 密码再次加盐加密 password:md5(password + HashSalt) }) if(ret._id){ this.success('新建成功') } }else{ this.error("验证码错误") } }
在app的model添加user.js 的数据字段
// 用户字段设计 module.exports = app=>{ let mongoose = app.mongoose let Schema = mongoose.Schema // 定义一个用户模型 const UserSchema = new Schema({ __v:{type:Number, select:false}, username: {type:String, required:true}, password: {type:String, required:true, select:false}, }, { timestamps:true}) return mongoose.model('User', UserSchema) }
4.JWT -- JSON WEB TOKEN
cnpm i egg-jwt -S
- 配置config
- plugin.js 开启插件
- router.js 里面针对哪个 url 想鉴权就加上 middleware
原理:
- 登录接口调用 sign 生成 token, 返回给客户端(cookie或者客户端自行保存到localstore)
- 鉴权的请求收到时,调用 verify 进行解码 token, 然后进行验证
在config文件下config.default.js添加
jwt:{ // let HashSalt = 'mengfei@123#$!321' secret:'mengfei@123#$!321' },
在config文件下plugin.js添加
exports.jwt = { enable: true, package: "egg-jwt" };
在app的middleware里面jwt.js
exports.jwt = { enable: true, package: "egg-jwt" };
router
module.exports = app => { const { router, controller } = app; router.get('/home', controller.home.index); router.get('/user/captcha',controller.user.captcha) const jwt = app.middleware.jwt({app}) // // 这个接口,需要登录后 才能获取到 // // 从token信息中,拿到用户数据,然后查库 返回 router.get('/user/info',jwt, controller.user.info); router.post('/user/register',controller.user.register) router.post('/user/login',controller.user.login) }