Node.js实现JWT应用到服务器
前言
JWT是用来解决跨域验证的,当我们在某个应用上注册,输入了用户名和密码之后并发送给服务器,服务器验证发送过来的用户名和密码以后会生成一个token
,并且发送给用户
当用户发送请求的时候一般会在HTTP的头部加上这个token
,服务器收到token
后进行验证,一般token
验证通过也没有过期的话,下次就不用重新输入用户名和密码了,服务器识别到头部的token
就返回给用户页面,所以token
非常重言,而生成的token
就用到了JWT这种数据结构
JWT就只有三个部分:头部,负载和签名
头部主要用来指明签名的算法
负载主要用来存放数据
签名是对头部和负载两个部分进行签名,签名里有个核心就是要定义一个密钥,这个密钥只有服务器知道
使用Node.js创建一个使用JWT的服务器
初始化
新建一个文件夹,在终端输入 npm init -y
进行初始化,并且安装express
和jsonwebtoken
这两个依赖,express是一个web应用框架,jsonwebtoken就是用来使用jwt的框架
npm init -y
npm i express jsonwebtoken
新建一个app.js作为服务器代码文件, 引入刚刚创建的依赖,创建一个名为app的应用,生成JWT所需要的密钥,调用express.json()
方法来解析json数据,最后监听端口
//引入依赖
const express = require('express')
const jwt = require('jsonwebtoken')
//创建名为app的express应用程序和jwt密钥
const app = express()
const jwtKey = 'abcdefghijk'
//解析JSON数据
app.use(express.json())
//监听端口
app.listen(3000,()=>console.log('server running'))
将服务器运行起来,终端打印出来了就表示没有问题
模拟登录
实际开发中开需要用到数据库,这里就创建一个database变量作为数据库数据
const database = {username:'admin',password:'123456'}
我们需要用post方法模拟一下用户登录的情况,使用 /login 作为登录路径,解构赋值将请求主体里的用户名和密码取出来,判断一下请求里的用户名和密码是否和数据库里的一致,一致的话就发送json数据给用户(实际开发中不要将密码回给用户,这里只是为了演示而已)
app.post('/login', (req, res) => {
const { username, password } = req.body //发送到服务器的用户名密码在请求主体里
if (username === database.username && password === database.password) {
res.json({ username, password, message: '登陆成功' }) //返回的json数据
}
})
这里在vscode里使用REST Client这个插件来模拟发送请求,可以在扩展里下载
创建一个请求文件,命名为request.http,将URL,头部和请求体填一下,请求体就是模拟用户发送的用户名和密码信息
点击最上面的Send Request发送,就可以看到服务器响应的内容了,成功返回了username,password,message
生成token
登录成功之后就可以生成token了,使用jsonwebtoken的sign
方法,这个方法对应着jwt的数据结构
首先填入负载,以对象的形式传入,这里就不传入用户的密码了,容易泄露,只传入一个username。然后填入私钥jwtKey
必选的参数填完了就可以传入一些可选的参数,比如token的有效期,使用expiresIn设置30秒有效时间,再传入一个函数,这个函数除了抛出错误信息还可以将token生成出来,我们就可以直接响应json数据了
jwt.sign(
{username},//负载
jwtKey,//密钥
{expiresIn:'30s'},//token有效时间
(err,token)=>{//函数生成token
res.json({
username,
message:'登录成功',
token
})
}
)
重新运行服务器再次点击Send Request,客户端就拿到token了
验证token
拿到token之后可以将cookie或者authorization头部发送给服务器
设置一个新的路径作为用户登录后跳转到另外的界面,另外的界面就不需要用户输入用户名和密码了
获取一下请求里的所有请求头并在控制台里输出
app.get('/afterlogin',(req,res)=>{
const headers=req.headers
console.log(headers);
})
在request.http里新增一条GET请求,添加authorization头部,输入Bearer 空格 token
###
GET http://localhost:3000/afterlogin
Authorization: Bearer 刚刚生成的token
点击发送可以看到控制台里返回的头部信息,authorization是专门用来做认证的请求头,输入Bearer 空格 token
是为了遵守OAuth2.0规则
我们需要对获取到客户端发来的请求进行处理,把请求头authorization里的字符串转为数组然后取出索引为1的值,也就是token
服务器去除token之后就要对token进行验证,需要用到jsonwebtoken的verify方法,依次传入token,密钥,最后还是传入一个函数,如果发生错误就不允许该请求进一步访问,发送一个403给他尝尝,这个函数除了错误参数还有另一个参数,也就是生成jwt的负载
const token = headers['authorization'].split(' ')[1]
jwt.verify(token,jwtKey,(err,payload)=>{
if(err) res.sendStatus(403)
res.json({message:'认证成功',payload})
})
最后重新运行服务器来运行一下,服务器返回的json和verify里设置的内容一致
本文正在参加「金石计划 . 瓜分6万现金大奖」