前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用NodeJs(Express)搞定用户注册、登录、授权

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

作者头像
ccf19881030
发布2020-02-23 17:39:07
9.3K0
发布2020-02-23 17:39:07
举报
文章被收录于专栏:ccf19881030的博客ccf19881030的博客

前言

首先做一下声明,本篇博客来源于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镜像安装。 如下图所示:

查看node、npm、cnpm、express的版本
查看node、npm、cnpm、express的版本

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

代码语言:javascript
复制
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中如下图所示:

Rest-Client
Rest-Client

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

代码语言:javascript
复制
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

代码语言:javascript
复制
/* 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

代码语言:javascript
复制
/* 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

代码语言:javascript
复制
@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中如下图所示:

登录请求
登录请求

参考资料

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 编码前的准备工作:第三方库和rest-client插件安装
  • server.js
  • model.js
  • test.http
  • 遇到的问题
  • 编译运行
  • 参考资料
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档