当前位置:网站首页>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
边栏推荐
- JVM memory allocation - xms128m - xmx512m - XX: permsize = 128M - XX: maxpermsize = 512M
- Novice guidance and event management system in game development
- Zero basis to build a web search engine of its own
- How does cglib implement multiple agents?
- Event monitoring problem
- An article takes you to understand CSS3 picture border
- 轻量型 GPU 应用首选 京东智联云推出 NVIDIA vGPU 实例
- STM32F030K6T6兼容替换灵动MM32F031K6T6
- Bitcoin once exceeded 14000 US dollars and is about to face the test of the US election
- Git rebase is in trouble. What to do? Waiting line
猜你喜欢
STM32F030F4P6兼容灵动微MM32F031F4P6
Summary of common SQL statements
预留电池接口,内置充放电电路及电量计,迅为助力轻松搞定手持应用
2020-09-09:裸写算法:两个线程轮流打印数字1-100。
谷歌浏览器实现视频播放加速功能
ES6 learning notes (5): easy to understand ES6's built-in extension objects
Markdown tricks
Method of code refactoring -- Analysis of method refactoring
Understanding formatting principles
Unity performance optimization
随机推荐
image operating system windows cannot be used on this platform
How much disk space does a file of 1 byte actually occupy
How much disk space does a new empty file take?
非易失性MRAM存储器应用于各级高速缓存
ado.net and asp.net The relationship between
An article taught you to use HTML5 SVG tags
This project allows you to quickly learn about a programming language in a few minutes
ES6 learning notes (3): teach you to use js object-oriented thinking to realize the function of adding, deleting, modifying and checking tab column
2020-08-14:数据任务的执行引擎用的哪些?
超高频RFID医疗血液管理系统应用
2020-08-19:TCP是通过什么机制保障可靠性的?
How to manage the authority of database account?
Axios learning notes (2): easy to understand the use of XHR and how to package simple Axios
Interviewer: how about shardingsphere
MRAM高速缓存的组成
GitHub: the foundation of the front end
The legality of IPFs / filecoin: protecting personal privacy from disclosure
The 4th China BIM (digital construction) manager Summit Forum will be held in Hangzhou in 2020
2020-08-29:进程线程的区别,除了包含关系之外的一些区别,底层详细信息?
To Lianyun analysis: why is IPFs / filecoin mining so difficult?