目录
- 开发环境:node-15.4.0、npm-7.19.1、mongodb-4.2.2、create-react-app、egg.js、 window10、Visual Studio Code、MongoDBCompass
注册与登录
后端项目搭建
- 使用egg.js脚手架进行开发
npm install -g egg
npm install -g egg-init
mkdir website-server
cd website-server
egg-init --type=simple
npm install
- 本项目数据库基于MongoDB,使用Egg.js官方提供的egg-mongoose插件安装依赖
npm install --save egg-mongoose
- 修改website-server中的config/plugin.js以启动egg-mongoose插件
'use strict';
/** @type Egg.EggPlugin */
module.exports = {
mongoose: {
enable: true,
package: 'egg-mongoose',
},
};
- 同时在website-server的config/config.default.js中添加Mongoose配置信息
/* eslint valid-jsdoc: "off" */
'use strict';
/**
* @param {Egg.EggAppInfo} appInfo app info
*/
module.exports = appInfo => {
/**
* 省略未修改代码
*/
// add your middleware config here
config.middleware = [];
config.mongoose = {
client: {
url: 'mongodb://127.0.0.1:27017',
options: {},
}
};
// add your user config here
const userConfig = {
// myAppName: 'egg',
};
return {
...config,
...userConfig,
};
};
- 然后启动项目
npm run dev
- 修改website-server中config/config.default.js文件,关闭CSRF防护
/** 省略未修改的代码 */
module.exports = appInfo => {
/** 省略未修改的代码 */
// add your user config here
const userConfig = {
security: {
csrf: {
enable: false
}
}
};
return {
...config,
...userConfig,
};
};
注册API
- 修改website-server中app/router.js文件
'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const { router, controller } = app;
/** 将路由未“/register”的POST请求交给user控制器中的register方法处理 */
router.post('/register', controller.user.register);
};
- 添加website-server中app/controller/user.js文件
const Controller = require('egg').Controller;
class UserController extends Controller {
async register() {
const { ctx } = this;
/** ctx。request.body得到网络访问的请求体 */
const { username, password } = ctx.request.body;
/** 调用业务逻辑下的register方法 */
await ctx.service.user.register(username, password);
ctx.body = { username, password };
}
}
module.exports = UserController;
- 使用curl工具访问注册接口http://localhost:7001/register
- 略
- 在website-server下新建模型app/model/user.js文件
'use strict'
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
const UserSchema = new Schema({
username: { type: String },
password: { type: String },
create_at: { type: Date, default: Date.now },
update_at: { type: Date, default: Date.now },
});
return mongoose.model('User', UserSchema);
};
- 在website-server下创建业务逻辑的抽象封装app/service/user.js文件
'use strict'
const crypto = require('crypto');
const Service = require('egg').Service;
class UserService extends Service {
async register(username, password) {
/** 获取User模型 */
const user = new this.ctx.model.User();
/** 对密码进行加密 */
const pwd = crypto.createHash('md5').update(password).digest('hex');
user.username = username;
user.password = pwd;
return user.save();
}
}
module.exports = UserService;
- 使用curl工具访问注册接口http://localhost:7001/register
- 略
- 使用MongoDBCompass可以查看到users集合中新增的user数据
登录API
- 在website-server的app/router.js添加路由:
/** 省略未修改代码 */
module.exports = app => {
const { router, controller } = app;
router.post('/register', controller.user.register);
router.post('/login', controller.user.login);
};
- 在app/service/user.js添加login()方法
/** 省略未修改代码 */
async login(username, password) {
const { ctx } = this;
let pwd = crypto.createHash('md5').update(password).digest('hex');
/** 调用egg中的findOne方法 */
let user = await ctx.model.User.findOne({ username, password: pwd });
return user;
}
/** 省略未修改代码 */
- 在app/controller/user.js添加login()方法
/** 省略未修改代码 */
async login() {
const { ctx } = this;
const { username, password } = ctx.request.body;
let user = await ctx.service.user.login(username, password);
ctx.body = { status: user?'ok' : 'error'};
}
/** 省略未修改代码 */
- 要实现登录功能,鉴权是必不可少的。本项目使用JWT实现鉴权
- 使用npm安装egg-jwt依赖包
npm install --save egg-jwt
- 在config/plugin.js启动egg-jwt插件
'use strict';
/** @type Egg.EggPlugin */
module.exports = {
mongoose: {
enable: true,
package: 'egg-mongoose',
},
jwt: {
enable: true,
package: "egg-jwt",
},
};
- 在config/config.default.js中添加JWT配置信息
/** 省略未修改代码 */
config.jwt = {
secret: "jwt_secret"
};
/** 省略未修改代码 */
- 修改app/controller/user.js文件
/** 省略未修改代码 */
async login() {
const { ctx } = this;
const { username, password } = ctx.request.body;
const user = await ctx.service.user.login(username, password);
if (user) {
const token = await ctx.app.jwt.sign({
username: user.username,
id: user._id
},
/** 使用JWT配置的secret值作为密钥 */
this.config.jwt.secret,
{
/** 设置有效时间(秒) */
expiresIn: 3600
}
)
ctx.body = { status: 'ok' , token};
} else {
ctx.body = {
status: 'error',
};
}
}
/** 省略未修改代码 */
- 使用curl工具访问注册接口http://localhost:7001/login
- 略
- 鉴于每次请求都要预先处理,使用中间件编写此逻辑,新建app/middleware/jwt.js文件
module.exports = options => {
return async function jwt(ctx, next) {
const token = ctx.request.header.authorization;
if (token) {
let decode = ctx.app.jwt.verify(token ,options.secret);
if (decode.exp > parseInt(new Date().getTime() / 1000)) {
return await next();
}
}
ctx.status = 401;
ctx.body = {};
return;
};
};
-
至此,注册与登录功能的API完成了
-
摘取自《React+Node.js实战开发》