专栏首页ccf19881030的博客使用NodeJs(Express)搞定用户注册、登录、授权

使用NodeJs(Express)搞定用户注册、登录、授权

前言

首先做一下声明,本篇博客来源于BiliBili上全栈之巅主播Johnny的视频[1小时搞定NodeJs(Express)的用户注册、登录和授权(https://www.bilibili.com/video/av49391383),对其进行了整理。自己跟着视频做,感觉收获不少。 最近在学些NodeJsExpress框架开发后台接口,Express 是一个保持最小规模的灵活的 Node.js Web 应用程序开发框架,为 Web 和移动应用程序提供一组强大的功能。看到B站上全栈之巅-Node.js+Vue.js全栈开发深度爱好者和实践者,感觉Johnny博主的系列视频讲解得不错,其中看到一个视频是1小时搞定NodeJs(Express)的用户注册、登录和授权,介绍了在Express中怎么做用户登录和注册,以及jsonwebtoken的验证,需要在系统中安装MongoDB数据库;于是在自己的Windows10系统下使用VSCode跟着做,前提是要安装好NodeJs和Express开发环境,以及在Windows系统中配置好MongoDB数据库,关于在Windows下安装MongoDB可以参考菜鸟教程中的Windows 平台安装 MongoDBwindows环境下启动mongodb服务

编码前的准备工作:第三方库和rest-client插件安装

我的nodejs版本是:v10.16.0, npm版本是:6.9.0,cnpm的版本是6.1.0,express的版本是4.16.1,由于npm在国内安装比较慢,最好用淘宝的cnpm镜像安装。 如下图所示:

使用到的第三方库有:express、jsonwebtokenbcryptjsmongoosenodemon用于调试

cnpm install express@next
cnpm install -g nodemon
cnpm install jsonwebtoken
cnpm install bcryptjs
cnpm install mongoose

另外,还需要在VSCode中安装扩展的rest-client插件,它是用于在VSCode中发起http请求的一个插件,可以通过代码的方式发起http请求,包括get、post、put去请求。类似于Postman,Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。其中Rest-Client插件在VSCode中如下图所示:

创建一个EXPRESS-AUTH的文件夹,在VSCode中打开此文件夹,然后使用如下命令安装好依赖库

cnpm install express@next
cnpm install -g nodemon
cnpm install jsonwebtoken
cnpm install bcryptjs
cnpm install mongoose

然后分别在EXPRESS-AUTH文件夹下创建test.http、server.js、model.js,分别表示发起http请求的文件,服务接口文件、MongoDB Model接口文件

server.js

/* jshint esversion: 8 */ 
// const mongoose = require('mongoose')
const { User } = require('./models')
const express = require('express')
const jwt = require('jsonwebtoken')

const app = express();
app.use(express.json())

const SECRET = "fdfhfjdfdjfdjerwrereresaassa2dd@ddds"

// app.get('/', async(req, res) => {
//   res.send('ok')
// })

app.get('/api', (req, res) => res.send('Hello World!'))

// 从MongoDB数据库express-auth中的User表查询所有的用户信息
app.get('/api/users', async(req, res) => {
  const users = await User.find()
  res.send(users)
})

app.post('/api/register', async (req, res) => {
  // console.log(req.body)
  // 在MongoDB数据库表USer中新增一个用户
  const user = await User.create({
    username: req.body.username,
    password: req.body.password,
  })

  // res.send('register')
  res.send(user)
})

app.post('/api/login', async (req, res) => {
  // res.send('login')
  // 1.看用户是否存在
  const user = await User.findOne({
    username: req.body.username
  })
  if (!user) {
    return res.status(422).send({
      message: '用户名不存在'
    })
  }
  // 2.用户如果存在,则看密码是否正确
  const isPasswordValid = require('bcryptjs').compareSync(
    req.body.password,
    user.password
    )
    if(!isPasswordValid) {
      // 密码无效
      return res.status(422).send({
        message: '密码无效'
      })
    }
  // 生成token
  const token = jwt.sign({
    id: String(user._id),
  }, SECRET)

  res.send({
    user,
    token
  })
})

// 中间件:验证授权
const auth = async (req, res, next) => {
   // 获取客户端请求头的token
   const rawToken = String(req.headers.authorization).split(' ').pop()
   const tokenData = jwt.verify(rawToken, SECRET)
  //  console.log(tokenData)
   // 获取用户id
   const id = tokenData.id;
  //  const user = await User.findById(id)
  req.user = await User.findById(id)
  next()
}

app.get('/api/profile', auth, async (req, res) => {
  res.send(req.user)
})

app.listen(3001, () => {
  console.log('http://localhost:3001')
})

model.js

/* jshint esversion: 8 */ 
const mongoose = require('mongoose')

// const bcrypt = require('bcrypt')
// const saltRounds = 10

// const bcrypt = require('bcryptjs')

mongoose.connect('mongodb://localhost:27017/express-auth', {
  useNewUrlParser:true,
  useUnifiedTopology: true,
  useCreateIndex: true
})

const bcrypt = require('bcryptjs')

// 定义一个用户模型,username是唯一的索引,表示不能被重复
const UserSchema = new mongoose.Schema({
  username: { type: String, unique: true },
  password: { 
    type: String, 
    set(val) {
      // var hash = bcrypt.hashSync(val, saltRounds)
      // return require('bcrypt').hashSync(val, 10)
      var salt = bcrypt.genSaltSync(10)
      var hash = bcrypt.hashSync(val, salt)
      return hash
    }
  },
})

// create the model for users and expose it to our app
const User = mongoose.model('User', UserSchema)

// 删除用户集合
// User.db.dropCollection('users')

module.exports = { User }

test.http

@url=http://localhost:3001/api
@json=Content-Type: application/json

###

get {{url}}

###
post {{url}}

### 查询所有用户
get {{url}}/users

### 注册
post {{url}}/register
# Content-Type: application/json
{{json}}

{
  "username": "user4",
  "password": "123456"
}

### 登录
post {{url}}/login
{{json}}

{
  "username": "user4",
  "password": "123456"
}

### 个人信息
get {{url}}/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlNDc1ODcyOTM2Mjg2NWE0MDk4YmRhYSIsImlhdCI6MTU4MTczNTAyM30.Nm6UhPY7EfP-WQIDFldayXzFoJlt5oIgVhidzDPy0gc

遇到的问题

其中遇到一个问题是,跟着视频使用bcrypt对用户密码进行散列加密时报错,换成bcryptjs库就OK了。

编译运行

在VSCode中打开终端,进入EXPRESS-AUTH目录,执行nodemon .\server.js开启服务端,服务器会在对应的3001端口上监听客户端的http请求,然后打开test.http文件,在相应的登录、注册、查询所有用户的请求,使用Ctrl+鼠标单击按住Send Request,发起对应的get、post请求,其中登录的请求在VSCode中如下图所示:

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Express.js Tutorial: Build RESTful APIs with Node and Express | Mosh

    在Youtube上看到Mosh的一篇关于使用Node和Express构建RESTful APIs的示例,对应的视频地址是:Express.js Tutorial...

    ccf19881030
  • 在Express中对MongoDB数据库进行增删改查

    这两天跟着B站的Johnny老师学习NodeJs+Express+MongoDB相关的知识点,前后跟着做了1小时搞定NodeJs(Express)的用户注册、登...

    ccf19881030
  • JSON.parse() and JSON.stringify()

    最近发现一个比较好的关于前端的英文博文网站,主要是关于Javascript、Vuejs、React、Angular、CSS的前端网站博文网站,网站地址是:htt...

    ccf19881030
  • 【笔记】实现一个简易的Promise

    const PENDING_STATE = "pending"; const FULLFILL_STATE = "fullfilled"; const REJE...

    SmileSmith
  • 经典面试题-Java中接口和抽象类的区别

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    cwl_java
  • 自动化篇 | 再也不用担心老人们用智能机了

    由于智能机操作的复杂性,很多老年人的手机使用一段时间之后,不知不觉间,下载了一大堆垃圾软件,内存占用越来越大,机器越用越卡。

    AirPython
  • 【译】银行高管权衡大数据对风险管理的价值

    大数据文摘
  • Android开发之自动填充短信验证码

    笔者发现在很多应用中,都有自动获取验证码的功能:点击获取验证码按钮,收到短信,当前应用不需要退出程序就可以获取到短信中的验证码,并自动填充。觉得这种用户体验很赞...

    YungFan
  • iOS数据持久化之二——归档与设计可存储化的数据模型基类

            在上一篇博客中,我们介绍了用plist文件进行数据持久化的方法。虽然简单易用,但随着开发的深入,你会发现,这种方式还是有很大的局限性。试想,如果...

    珲少
  • Fiori应用里application dependency里奇怪的manifest url是从哪来的

    GM6上我们own的application的application dependency里发现都有这样奇怪的manifest url,但是BP的却没有。

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券