关于eggjs:如何用Eggjs从零开始开发一个项目2

4次阅读

共计 3661 个字符,预计需要花费 10 分钟才能阅读完成。

在上一篇文章,咱们曾经应用 Sequelize 连贯上了数据库,并能进行简略的数据库操作,在此基础上,咱们试着来开发一个残缺的我的项目。这篇文章咱们从用户的注册、登录着手,试着开发用户模块的相干的代码。

用户注册

1. 注册逻辑

用户注册的逻辑很简略:

  • 客户端:用户输出输出账号,明码等信息进行用户注册;
  • 服务端:接管到客户端提交的注册信息后,进行字段的测验(是否必填、字段长度等),字段符合要求后,依据用户注册的账号查询数据库,依据返回后果判断该用户是否是新用户,如果是新用户,将用户信息写入到数据库,实现注册流程。

2. 用户明码解决

客户端用户提交数据后,服务端验证通过进行数据库写入,然而其中用户明码是敏感信息,为了服务平安思考,不能间接将明文明码写入到数据库,避免数据库被攻打,用户明码泄露。所以个别在存储用户明码时,会先对用户明码进行加盐加密解决,这样哪怕数据库存储的明码泄露,其他人也无奈通过解决后的明码进行登录。这里应用哈希算法对明码进行加密,因为哈希的个性是不可逆,具体的细节能够参考为什么说 MD5 是不可逆的?。阐明:哈希能够被暴力破解,加盐能够很大水平上减少破解难度。

废话不多说,咱们上面来写代码。

首先,咱们装置一下bcryptjs,咱们应用它对明码进行加盐加密和比对:

npm install bcryptjs --save

而后咱们把这两个办法写到app/extend/helper.js

const bcrypt = require('bcryptjs');
module.exports = {encrypt(password) {const salt = bcrypt.genSaltSync(5);    // 加盐
        const hash = bcrypt.hashSync(password, salt);    // 哈希(同步调用)return hash;
    },
    compare(password, hash) {return bcrypt.compareSync(password, hash);    // 比对
    }
};

这样咱们在我的项目里就能够通过 this.ctx.helop.encryptthis.ctx.helop.compare的形式去应用这些专用的办法了。

而后,在 UserController 中增加一个 register 办法:

async register() {
    const params = this.ctx.request.body;
    // 参数校验
    if (!params.name || !params.password || !params.phone || !params.email) {
        this.ctx.body = {
            code: '500',
            msg: '参数不非法'
        };
    }
    // 查问该用户是否曾经注册
    const user = await this.ctx.model.User.findOne({ where: {name: params.name} });

    if (user) {
        this.ctx.body = {
            code: '500',
            msg: '该用户已存在'
        };
    }
    // 插入数据库
    const result = await this.ctx.model.User.create({
        ...params,
        password: this.ctx.helper.encrypt(params.password)
    });
    if (result) {
        this.ctx.body = {
            code: '200',
            msg: '注册胜利'
        };
    }
}

最初,增加路由:

// app/router.js
router.post('/register', controller.user.register);

3. 功能测试

测试一下,用 postman 创立一个 post 申请到localhost:7001/register,传入注册用户信息:

{
    "name":"xiaoming",
    "password":"test1234",
    "phone":"13412341234",
    "email":"test@gmai.com"
}

服务端返回“注册胜利”的提醒语,这时候咱们去数据库就能看到这条数据了,而且明码是一坨看不懂的密文,这个时候咱们用同样的数据再次发动申请,服务端返回“该用户已注册”,阐明咱们的注册性能曾经实现了!

用户登录

用户登录的逻辑很简略,就是一个客户端传入的用户名明码与服务器存储的相比拟,匹配就登录胜利,不然就是用户名明码谬误。然而,咱们还须要额定思考一个问题,http 申请是无状态的,那咱们怎么去记住用户的登录状态和登录信息呢,并且每次向服务端发动申请都带上这些信息呢?

罕用的用户认证形式有两种,一种是通过 Cookie 实现,一种是 Token 的实现形式。对于用户受权认证能够看看这篇文章:受权认证登录之 Cookie、Session、Token、JWT 详解,Eggjs 官网也有一个章节讲了 Cookie 和 Session 相干的常识 Cookie 与 Session,学习服务端,把握这些常识还是很必要的。

在这里,咱们抉择 JWT 作为咱们的解决方案。对于 JWT,这里提供两篇文章作为参考,JSON Web Token 入门教程,Introduction to JSON Web Tokens。OK,原理看完当前咱们来写代码。

首先咱们装置 egg-jwt 插件:

npm install egg-jwt --save

引入插件:

// app/config/plugin.js
jwt: {
    enable: true,
    package: "egg-jwt"
}

配置 jwt secret:

// app/config/config.default.js
config.jwt = {secret: '12312456};

OK,咱们上面编写代码的代码:

// app/controller/user.js
async login() {
    const params = this.ctx.request.body;
    if (!params.name || !params.password) {
        this.ctx.body = {
            code: '500',
            msg: '参数不非法'
        }
    }

    const user = await this.ctx.model.User.findOne({ where: {name: params.name} });

    if (!user) {
        this.ctx.body= {
            code: '500',
            msg: '用户名明码谬误'
        }
    }

    // 校验明码
    const checkPassword = this.ctx.helper.compare(
        params.password,
        user.password
    );

    if (checkPassword) {
        // 依据用户名称创立 token,过期工夫为 2 小时
        const token = this.app.jwt.sign({name: user.name}, this.app.config.jwt.secret, {expiresIn: '2h'});
        this.ctx.body = {
            code: '200',
            data: token
        }
    } else {
        this.ctx.body = {
            code: '500',
            msg: '用户名明码谬误'
        }
    }
}

配置路由:

// app/router.js
router.post('/login', controller.user.login);

代码结束,让咱们测试一下,创立一个 post 申请到localhost:7001/login,输出用户名明码:

{
    "name":"xiaoming",
    "password":"test1234"
}

后果如下:

{
    "code": "200",
    "data": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoieGlhb21pbmciLCJpYXQiOjE2MDg1NTkzMTYsImV4cCI6MTYwODU2NjUxNn0.SyXAhVvrwAql-4FzaZrlEs6dsEJ4wXbdjQsHv43CSOI"
}

胜利了,这一大坨就是咱们创立的 token。

嗯……咱们是拿到了 token,然而怎么用呢?还记得咱们最开始写的两个接口吗?咱们当初给他配置 jwt 验证,而后试试不登录能不能拜访。

// app/router.js
router.post('/createUser', app.jwt, controller.user.createUser);
router.get('/getUsers', app.jwt, controller.user.getUsers);

而后咱们从新测试一下这两个接口,服务端返回 401 Unauthorized,这阐明验证失效了。那咱们在申请的时候把方才登录接口获取到的 token 设置在AuthorizationBearer Token字段中,再试一次,胜利了!

如果你跟我走到了这一步,那阐明你曾经间隔一个合格的服务端开发者更近了一步,然而这里咱们如同并没有用到 token 外面携带的信息,下一篇咱们将会解析 token 携带的信息,晓得每次都是哪个用户在拜访咱们的服务,而且咱们将优化咱们的代码,让它看起来更简洁、正当。

正文完
 0