使用node/koa/mongodb实现的jwt登录注册

思路 :
实现登录注册有三种方式 session和jwt 和oAuth(第三方登录) 我这里选用jwt

需要
中间件 koa-jwt 权限路由验证
jsonwebtoken 生成token

密码加密

  • uuid —唯一识别码
  • sha1 —安全哈希算法
  • bcrypt —加密算法
  • crypto —加密算法
  • md5 –加密算法

json web token 传输方式
用md5/sha1+salt的方法保存密码是不安全的, 保存密码推荐用Bcrypt.

登录的几种实现方式
1.session 接收用户传过来的信息,存在session中,以cookie的方式传回给浏览器,cookie中有sessionId及值,
从http header中提取session Id ,根据session Id 从服务器端的hash中获取请求者身份

2.token 服务端收到信息后,将username转为userId 存储在jwt的payload中, 与头部进行base64编码进行签名,形成jwt,在cookie中保存,返回给浏览器,
浏览器每次请求都携带cookie,服务器对jwt进行解密,与服务器进行比较

项目流程
我使用了koa-generator脚手架, 热更新npm run dev ,服务器可以自动刷新,但是浏览器需要自己刷新

连接mongodb

用powershell运行似乎和cmd运行有点不一样
1 下载 安装

2 创建一个data文件夹来保存文件 目录C:\data\db 这是mongodb的默认路径

运行:C:\mongodb\bin\mongod –dbpath c:\data\db 连接C:\mongodb\bin\mongo.exe

3 一些帮助db.help() db.stats()查看 show dbs

4 切换数据库 use mydb

5 Mongoose是MongoDB的一个对象模型工具,Mongoose,因为封装了对MongoDB对文档操作的常用处理方法,可以高效的操作mongodb象模型工具,Mongoose,
因为封装了对MongoDB对文档操作的常用处理方法,可以高效的操作mongodb,同时可以理解mongoose是一个简易版的orm

6 app.js 连接数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var mongoose = require('mongoose')
mongoose.connect("mongodb://127.0.0.1:27017/user", { //mongoose.connect
useNewUrlParser: true
});
// MongoDB连接成功后回调,这里仅输出一行日志
mongoose.connection.on('connected', function () { //mongoose.connection
console.log('sucess 192.168.1.29:27017/user');
});

// MongoDB连接出错后回调,这里仅输出一行日志
mongoose.connection.on('error', function (err) {
console.log(' error: ' + err);
});

// MongoDB连接断开后回调,这里仅输出一行日志
mongoose.connection.on('disconnected', function () {
console.log(' disconnected');
});

7 和koa连接是使用mongoose,根目录下新建一个models文件夹,这里放置数据模型,

1
2
3
4
5
6
7
8
9
models/userinfo.js文件
var mongoose = require('mongoose')
var schema = mongoose.Schema
const userinfo = new schema({
'username': String,
'password': String
})
const user = mongoose.model('userinfo', userinfo)
module.exports = user

koa-router 使用

引入和获取一个router实例

1
2
3
4
5
const router = require('koa-router')()
router.get('/')
router.post('/')
router.use(userinfo.routes(), userinfo.allowedMethods())
router.use(home.routes(), home.allowedMethods())

这里可以把router分文件写,然后写一个index汇总,在app.js里引入

在router文件夹里面router/user.js
登录注册的主要思路是注册时给密码加密(忽略验证等其他方面的),然后登录时验证如果密码匹配就返回token,然后如果有鉴权的需要,则前端每个http请求需要在header中携带token,然后node后端中验证token是否有效,这个验证koa-jwt已经在作用了,对于token登出这一块,需要存储token,然后比对,前后端都清除,还有一种是不存储token,设置过期时间,仅前端登出

登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
router.post('/login', async (ctx, next) => {
const userinfos = await user.findOne({
username: ctx.request.body.username
})

const compare = await bcrypt.compare(ctx.request.body.password, userinfos.password)
if (compare) {
ctx.body = {
code: 1,
msg: '登录成功!',
token: jsonwebtoken.sign({
data: userinfos.username,
exp: Math.floor(Date.now() / 1000) + (60 * 60)
}, 'secret')
}
} else {
ctx.body = {
code: 0,
msg: '登录失败!'
}
}
})
//注册
router.post('/register', async (ctx, next) => {
//判断和唯一识别码
const {
body
} = ctx.request
body.password = await bcrypt.hash(ctx.request.body.password, 10)
const res = await user.create(body)
if (res) {
ctx.body = {
code: 1,
msg: '注册成功!'
}
} else {
ctx.body = {
code: 0,
msg: '注册失败!'
}
}
})

路由鉴权

1
2
3
4
5
6
7
8
app.js
//koa-jwt 路由鉴权
app.use(errorHandle)
app.use(jwt({
secret: 'secret'
}).unless({
path: [/\/register/, /\/login/]
}))