这两个页面的实现主要使用到的就是 element-ui 中的 form 表单和 input 组件,页面的搭建比较简单就不再这里过多说明了。
1.对 vue 进行基础配置
devServer: {
port: 8848, //端口号
host: "localhost", //端口
https: false, //是否使用 https 协议
open: false, //每次启动是否自动在页面打开
proxy: { //代理配置
"/api": {
target: 'http://localhost:3000', //后端接口名称
changeOrigin: true, //是否跨域
pathRewrite: { //路由转发
"^/api": "",
}
}
},
},
2.安装 axios
npm i axios
3.新建 request.js 文件用于发送请求
import axios from "axios";
const BASE_URL = "/api";
const request = axios.create({
baseURL: BASE_URL,
timeout: 5000,
});
export default request;
4.新建 api 文件夹,创建 logoApi.js
import request from "@/utils/request" //引用 request
export function index(data) {
return request({
url: '/login', //请求路径
method: 'post', //请求方法
data: data //附带的数据
})
}
5.安装 cors
npm i koa2-cors
6.在 app.js 中引入 cors ,用于解决跨域问题
const cors = require("koa2-cors")
app.use(cors())
7.在 node 端,router 文件夹下创建 login.js
const router = require("koa-router")(); //引入路由
const login = require("../controller/api/login") //引入自己编写实现文件
router.prefix('/login'); //提出公共路径
router.post('/', login.index); //路由路径
module.exports = router;
8.在 app.js 中,添加路由
const login = require('./routes/login')
app.use(login.routes(), login.allowedMethods())
9.新建 controller 文件夹,在其下新建 admin 文件夹,新建 login.js
const login = require('../../server/login')
module.exports = {
async index(ctx, next) {
ctx.response.body = {
flag: true,
errMsg: "query:OK",
statusCode: 200,
}
}
}
经过上面9步,就连通了服务器,并且解决了跨域的问题。
1.安装 mongoose
npm i mongoose
2.新建 config 文件夹,创建 db.js
const mongoose = require('mongoose')
const options = {
useMongoClient: true,
autoIndex: false,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
poolSize: 10,
bufferMaxEntries: 0,
type: 'mongodb', // 数据库类型
hostname: "localhost", // 服务器地址
hostport: 27017, // 默认端口号
database: "b0341-Library", // 数据库名称
username: '', // 访问数据库用户名
password: '', // 访问数据库密码
charset: 'utf8', // 字符集
prefix: '', // 表前缀 mysql b0335-admin
};
mongoose.connect(`${options.type}://${options.hostname}:${options.hostport}/${options.database}`);
const db = mongoose.connection;
db.on('error', (error) => {
console.log('数据库连接错误: ', error);
});
module.exports = db;
数据库连接成功。
1.注册页面获取用户输入信息
formDate: {
username: "",
password: "",
passwords: "",
gender: "",
phone: "",
hobbies: [],
email: "",
select: "",
postbox: "",
},
submit() {// 注册按钮
this.formDate.postbox = this.formDate.email + this.formDate.select;
this.$delete(this.formDate, "passwords");
this.$delete(this.formDate, "email");
this.$delete(this.formDate, "select");
addUser(this.formDate)
.then((response) => {
if (response.data.flag) {
this.$router.push("/");
}
})
.catch((error) => {
console.log(error);
});
},
2.配置路由,api 文件夹下,新建 register.js
import request from "@/utils/request";
export function addUser(data) {
return request({
url: "/register/add",
method: "post",
data: data
});
}
3.node 端,新建 model 文件夹,创建 user.js
const mongoose = require("mongoose");
const db = require('../config/db')
const Schema = mongoose.Schema;
const userSchema = new Schema(
{
user_name: String,
user_password: String,
user_gender: String,
user_phone: Number,
user_hobbies: Schema.Types.Array,
user_postbox: String,
user_identity: {
type: String,
default: "user"
},
user_credit: {
type: Number,
default: 0
}
},
{
timestamps: {
createdAt: "create_time",
updatedAt: "update_time",
},
}
);
const user = mongoose.model("User", userSchema);
module.exports = user;
对 user 的数据规定
4.创建 router/rejister.js ,并在 app.js 引入路由
const router = require('koa-router')()
const register = require("../controller/api/register")
router.prefix('/register')
router.post('/add', register.addUser);
module.exports = router
5.创建 server 文件夹,用于实现数据库操作,新建 rejister.js
const user = require('../model/user');
async function addUser(date) {
try {
const userSchema = new user(date);
const result = await userSchema.save();
if (!result) {
return {
flag: false,
errMsg: "query:error"
}
}
return { flag: true, errMsg: "query:success", data: result }
} catch (error) {
return {
flag: false,
errMsg: error
}
}
}
module.exports = {
addUser
}
6.创建 controller/api/register.js
const register = require('../../server/register')
module.exports = {
async addUser(ctx, next) {
const { username, password, gender, phone, hobbies, postbox } = ctx.request.body;
const date = {
user_name: username,
user_password: password,
user_gender: gender,
user_phone: phone,
user_hobbies: hobbies,
user_postbox: postbox,
}
const { data, flag } = await register.addUser(date);
ctx.response.type = "application/json";
if (flag) {
ctx.response.body = {
flag: true,
statusCode: 200,
errMsg: "query:OK",
data
}
};
}
}
用户注册的流程就是这样,但是我这里前端用户信息输入的 rule 还没有写,后续会补。
注册的功能实现了。
1.前端将用户名和密码发送到后端。
2.后端验证用户名和密码,生成 token 返回前端。在之后的请求中,都会加入 token ,后台会检验 token ,token 正确进行下一步操做,token 错误跳回登录页。
1.安装 jsonwebtoken
npm i jsonwebtoken
2.生成 token
const key = "b0341library" //密钥
let token = jwt.sign({
data: data[0].user_name //数据
}, key, { expiresIn: 60 * 6 }); //有效时间
4.token 验证
在 node 端,新建 middleware/JwtToken.js ,在 app.js 中引用
return async (ctx, next) => {
const { authorization } = ctx.request.header;
let token = "";
if (authorization) {
token = authorization.split(" ")[1];
}
console.log(token, "token");
if (token) {
//解析 token
jwt.verify(token, key, async function (error, data) {
if (error) {
if (error.name == 'TokenExpiredError') {//token过期
console.log("token过期");
return (ctx.response.body = {
flag: false,
errMsg: "token过期",
statusCode: 401,
data,
});
} else if (error.name == 'JsonWebTokenError') {//无效的token
console.log("无效的token");
return (ctx.response.body = {
flag: false,
errMsg: "无效的token",
statusCode: 401,
data,
});
}
}
let user_name = data.data;
const result = await user.findOne({ user_name });
if (result) {
return (ctx.response.body = {
flag: true,
errMsg: "查询成功",
statusCode: 200,
data: result.data,
})
} else {
return (ctx.response.body = {
flag: false,
errMsg: "没查到用户信息",
statusCode: 400
});
}
});
await next();
} else {
if (whiteList.includes(ctx.request.url)) {
await next();
} else {
return (ctx.response.body = {
flag: false,
errMsg: "没查到用户信息",
statusCode: 401,
data: null,
});
}
}
};
const JwtToken = require("./middleware/JwtToken.js")
app.use(JwtToken())
首先,解析 token ,token 无效或过期都不能进行下一步操作;token 有效,利用解析 token 得到的数据进行查询,如果有这个用户就可以进行下一步操作,否则依旧不可以进行下一步操作。
与注册相同就不重复了
1.在 request.js 中加入请求拦截和相应拦截
// axios 请求拦截
request.interceptors.request.use(
(config) => {
// 请求拦截中加上token
// 并不是所有的请求都需要带token 登录的请求
if (!whiteList.includes(config.url)) {
const token = getToken() || null;
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// axios 响应拦截
request.interceptors.response.use(
(response) => {
const responseData = response.data;
if (!responseData.flag && responseData.statusCode !== 200) {
Message({
message: "用户名或密码错误",
type: "error",
duration: 5 * 1000,
});
}
return responseData;
},
(error) => {
Message({
message: error.message,
type: "error",
duration: 5 * 1000,
});
return Promise.reject(error);
}
);
2.在 router/index.js 中加入路由守卫
router.beforeEach((to, from, next) => {
if (whiteList.includes(to.path)) {
next();
} else {
let token = localStorage.getItem('TOKEN_KEY');
if (!token) {
Message({
message: "请先登录",
type: "warning",
duration: 3 * 1000,
})
} else {
next();
}
}
})
3.使用 vuex 进行数据的处理
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user';
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
user
}
})
import { loginout, index } from "@/api/loginApi";
function getToken() {
return localStorage.getItem('TOKEN_KEY');
}
function setToken(token) {
return localStorage.setItem('TOKEN_KEY', token);
}
function removeToken() {
localStorage.removeItem('TOKEN_KEY');
}
const user = {
state: {
user: null, // 用户信息
token: getToken(), // token值 jwt
},
getter: {},
mutations: {
set_token(state, token) {
state.token = token;
setToken(token);
}
},
actions: {
Login({ commit }, formData) {
return new Promise((resolve, reject) => {
index(formData)
.then((response) => {
if (response.flag) {
commit("set_token", response.token);
}
resolve(response);
})
.catch((error) => {
console.log(error);
reject(error);
});
});
},
Loginout() {
return new Promise((resolve, reject) => {
loginout().then(response => {
removeToken();
resolve(response);
}).catch(error => {
reject(error);
})
})
}
},
};
export default user;
4.login 页面发送请求
submit() {
this.$store
.dispatch("Login", this.data)
.then((response) => {
if (response.flag) {
this.$router.push("/home");
} else {
this.$message.error("用户名或密码错误");
}
})
.catch((error) => {
console.log(error);
});
},
1.vue proxy 代理
vue:详解vue中的代理proxy
2.mongoose 操作
mongoose.js中文网
3.jsonwebtoken 详解
jsonwebtoken 中文文档
Json Web Token 详解
4.vuex
vuex官网
5.vue 路由守卫
vue-router