当前位置:网站首页>Nodejs中使用jsonwebtoken(JWT)生成token的场景使用
Nodejs中使用jsonwebtoken(JWT)生成token的场景使用
2020-11-06 22:11:00 【进击的前端】
Ⅰ- 壹 - jsonwebtoken简介
一 为什么需要 token
-
http 无状态
-
session 无法跨服务器
-
cors 跨域以后 cookie 无法使用
在前后分离的项目中,每次请求session都会变化,前端调用后端api接口,因此使用cors = require('cors')
来解决了跨域问题,而跨域对于cookie来说,就是两个不同的网站,因此session会不停的变。
在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般我们所说的的token大多是指用于身份验证的token
我们需要每次都知道当前请求的人是谁,但是又不想每次都让他提交用户名和密码,这时就需要有一个等同于用户名密码也能够标识用户身份的东西,即—token
二 什么是token
token是由三段式加密字符串组成以.
分开例如xxxxxxxxxxxxxxxxxxxxx.yyyyyyyyyyyyyyyyyyyyyyyy.zzzzzzzzzzzzz
-
第一段: 头, 签证: 安全信息验证, 你的口令, 进行不可逆加密*
-
第二段: 你要保存的信息: basa64 加密后截取内容,
-
第三段: 额外信息: 不可逆加密
第一段和第三段不可逆加密 哈希散列,第二段 base64 可逆加密
这一段字符串由后端发给前端,再登陆过以后, 生成一个 token 给到前端
Ⅱ - 贰 - jsonwebtoken的使用
一下载使用
npm i jsonwebtoken
||
yarn add jsonwebtoken
在nodejs中直接导入
// 0. 导入
const jwt = require('jsonwebtoken')
二 jsonwebtoken方法
1 生成token:
jwt.sign(你要保存的信息, 口令, 参数)
-
保存的信息
-
口令: 加密口令, 加密的时候混入信息使用, 解密的时候还要这个口令
-
参数: 是一个对象, {}
expiresIn: 过期时间,单位为秒 (‘1d’)*
2 解码token:
jwt.verify(你要解析的 token, 口令, 回调函数)
-
token: 必须是一个指定的 token
-
口令: 必须是加密时候的口令
-
回调函数: 接收结果
const express = require('express')
const jwt = require('jsonwebtoken')
const cors = require('cors')
const router = express.Router()
const app = express()
app.use(cors())
// 准备一个 token 验证的中间件
app.use(function (req, res, next) {
// req.url 表示当前地址
const {
url, headers: {
authorization: token } } = req
// const url = req.url
// const { authorization: token } = req.headers
// const token = req.headers.authorization
// 不需要验证的 请求地址
if (url === '/login' || url === '/banner') return next()
// 来到这里表示需要 token 验证
if (!token) return res.send({
message: '请携带 token 请求', code: 0 })
jwt.verify(token, 'Josiah', (err, data) => {
if (err && err.message === 'invalid token') return res.send({
message: '无效 token', code: 0 })
if (err && err.message === 'jwt expired') return res.send({
message: 'token 失效', code: 0 })
next()
})
})
router.get('/login', (req, res) => {
// 默认登录成功
const userInfo = {
username: 'XXX',
age: 18
}
// 生成一个 token 返回给前端
const token = jwt.sign(userInfo, 'Josiah, {
expiresIn: 60 })
res.send({
message: '登录成功', code: 1, token })
})
// 第二次测试
router.get('/cartInfo', (req, res) => {
res.send({
message: '获取购物车数据成功', code: 1 })
})
router.get('/pay', (req, res) => {
res.send({
message: '支付成功', code: 1 })
})
// 第一次测试
// router.get('/cartInfo', (req, res) => {
// 你想要购物车数据
// 那么你必须登录以后
// 验证 token 是不是正确
// req, 是本次请求的信息
// req.headers 就是本次的请求头
// const token = req.headers.authorization
// // 1. 有没有
// if (!token) return res.send({ message: '该请求需要 token', code: 0 })
// // 2. 对不对
// jwt.verify(token, 'guoxiang', (err, data) => {
// if (err && err.message === 'invalid token') return res.send({ message: '无效 token', code: 0 })
// if (err && err.message === 'jwt expired') return res.send({ message: 'token 失效', code: 0 })
// res.send({ message: '获取购物车数据成功', code: 1 })
// })
// })
router.get('/banner', (req, res) => {
// 你需要轮播图信息
// 不需要登录验证
res.send({
message: '轮播图数据获取成功', code: 1, list: [ {
}, {
} ] })
})
app.use(router)
app.listen(8080, () => console.log('running at 8080'))
三 测试使用
token的生成和解码
// 0. 导入
const jwt = require('jsonwebtoken')
// 准备一个信息
const userInfo = {
_id: '2131245655',
username: '小星星',
age: 18,
gender: '男'
}
// 1. 生成一个 token
const res = jwt.sign(userInfo, 'key', {
expiresIn: 20 })
console.log(res)
//res会生成一下内容
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
// eyJfaWQiOiIyMTMxMjQ1NjU1IiwidXNlcm5hbWUiOiLpg63nv5QiLCJhZ2UiOjE4LCJnZW5kZXIiOiLnlLciLCJpYXQiOjE1OTkxOTk2MDYsImV4cCI6MTU5OTE5OTYxNn0.
// Cg-PxkAzTnCUF9xja1O9gcOmRzaRsw4TlFM2nCZenAw
// 2. 解码
jwt.verify(res, 'key', (err, data) => {
console.log('第一次 1.5s')
if (err) return console.log(err)
console.log(data)
})
Ⅲ - 叁 - 第三方插件express-jwt
- 是一个express框架和jwt结合的第三方中间件
- 作用:验证token
- 用这个插件需要和sonwebtoken一起使用
注意:
- 如果你要使用 express-jwt你必须有一个全局错误中间件
- 正常的 token 返回给前端,需要写成 Bearer token
以下案例用到的插件:
express、jsonwebtoken、express-jwt、cors
app.js
const express = require('express')
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')
const cors = require('cors')
const router = expryicisess.Router()
const app = express()
app.use(cors());//解决跨域问题
// app.use() 里面放的 expressJWT().unless()
// 注册 token 验证中间件
app.use(expressJWT({
// 解析口令, 需要和加密的时候一致
secret: 'Josiah',
// 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
algorithms: ['HS256']
}).unless({
// 不需要验证 token 的路径标识符
path: ['/login', '/banner']
}))
router.get('/login', (req, res) => {
// 默认登录成功
const userInfo = {
username: '郭翔',
age: 18
}
// 生成一个 token 返回给前端
const token = 'Bearer ' + jwt.sign(userInfo, 'Josiah', {
expiresIn: 60 })
res.send({
message: '登录成功', code: 1, token })
})
app.use(router)
// 错误处理中间件
app.use((err, req, res, next) => {
res.send({
err })
})
app.listen(8080, () => console.log('running at 8080'))
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>登录</button>
<script>
// 如果你是做后台管理系统, 一般存储在 sessionStorage
// window.sessionStorage.setItem('abc', '100')
// 前端携带 token 我们存储在 请求头 里面携带
// authorization: token
const xhr = new XMLHttpRequest()
const token = window.localStorage.getItem('token')
xhr.open('GET', 'http://localhost:8080/cartInfo')
xhr.onload = function () {
const res = JSON.parse(xhr.responseText)
console.log(res)
}
xhr.setRequestHeader('authorization', token)
xhr.send()
</script>
</body>
</html>
0 - 0 - 知识点:
一 在生成token的时候
需要在生成之前添加 Bearer
后面有个空格
const token = 'Bearer ' + jwt.sign(userInfo, 'guoxiang', { expiresIn: 60 })
二在解析token的时候
- 解析口令, 需要和加密的时候一致
- 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
// app.use() 里面放的 expressJWT().unless()
// 注册 token 验证中间件
app.use(expressJWT({
// 解析口令, 需要和加密的时候一致
secret: 'guoxiang',
// 加密方式: SHA256 加密方式在 express-jwt 里面叫做 HS256
algorithms: ['HS256']
}).unless({
// 不需要验证 token 的路径标识符
path: ['/login', '/banner']
}))
三 在前端获取的时候
- 如果你是做后台管理系统, 一般存储在 sessionStorage
- 前端携带 token 我们存储在 请求头 里面携带,一般使用authorization
xhr.setRequestHeader('authorization', token)
版权声明
本文为[进击的前端]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4618999/blog/4706905
边栏推荐
- Detect certificate expiration script
- C calls SendMessage to refresh the taskbar icon (the icon does not disappear at the end of forcing)
- window系统 本机查找端口号占用方法
- What kind of music do you need to make for a complete game?
- ado.net和asp.net的关系
- 迅为-iMX6ULL开发板上配置AP热点
- Erd-online free online database modeling tool
- What is the tensor in tensorflow?
- 统计项目代码行数
- 2020-08-17:详细说下数据倾斜怎么解决?
猜你喜欢
2020-09-04:函数调用约定了解么?
Take you to learn the new methods in Es5
image operating system windows cannot be used on this platform
预留电池接口,内置充放电电路及电量计,迅为助力轻松搞定手持应用
Zhou Jie: database system of East China Normal University
All the way, I was forced to talk about C code debugging skills and remote debugging
小熊派开发板实践:智慧路灯沙箱实验之真实设备接入
2020-09-09:裸写算法:两个线程轮流打印数字1-100。
Those who have worked in China for six years and a million annual salary want to share these four points with you
Kubernetes and OAM to build a unified, standardized application management platform knowledge! (Internet disk link attached)
随机推荐
An article taught you to download cool dog music using Python web crawler
ES6 learning notes (5): easy to understand ES6's built-in extension objects
Flink's datasource Trilogy: direct API
An article will introduce you to CSS3 background knowledge
2020 database technology conference helps technology upgrade
Application insights application insights use application maps to build request link views
Filecoin has completed a major upgrade and achieved four major project progress!
磁存储芯片STT-MRAM的特点
Python basic variable type -- list analysis
[learning] interface test case writing and testing concerns
迅为-iMX6ULL开发板上配置AP热点
How much disk space does a file of 1 byte actually occupy
Qt音视频开发46-视频传输UDP版
image operating system windows cannot be used on this platform
Zero basis to build a web search engine of its own
嘉宾专访|2020 PostgreSQL亚洲大会阿里云数据库专场:曾文旌
面试官: ShardingSphere 学一下吧
Unity performance optimization
PHP application docking justswap special development kit【 JustSwap.PHP ]
list转换map(根据key来拆分list,相同key的value为一个list)