当前位置:网站首页>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
边栏推荐
- Erd-online free online database modeling tool
- What the hell is fastthreadlocal? The existence of ThreadLocal!!
- Can you do it with only six characters?
- image operating system windows cannot be used on this platform
- Elasticsearch database | elasticsearch-7.5.0 application construction
- Detect certificate expiration script
- Zero basis to build a web search engine of its own
- 检测证书过期脚本
- Zhou Jie: database system of East China Normal University
- Open source a set of minimalist front and rear end separation project scaffold
猜你喜欢
意派Epub360丨你想要的H5模板都在这里,电子书、大转盘、红包雨、问卷调查……
Unity performance optimization
非易失性MRAM存储器应用于各级高速缓存
An article will take you to understand SVG gradient knowledge
The native API of the future trend of the front end: web components
An article takes you to understand CSS3 picture border
Zhou Jie: database system of East China Normal University
Novice guidance and event management system in game development
The 4th China BIM (digital construction) manager Summit Forum will be held in Hangzhou in 2020
2020-08-15:什么情况下数据任务需要优化?
随机推荐
2020-08-19:TCP是通过什么机制保障可靠性的?
Helping financial technology innovation and development, atfx is at the forefront of the industry
To Lianyun analysis: why is IPFs / filecoin mining so difficult?
How to start the hidden preferences in coda 2 on the terminal?
How to manage the authority of database account?
NAND FLASH的接口控制设计
意派Epub360丨你想要的H5模板都在这里,电子书、大转盘、红包雨、问卷调查……
Flink's datasource Trilogy: direct API
[learning] interface test case writing and testing concerns
【涂鸦物联网足迹】物联网基础介绍篇
es创建新的索引库并拷贝旧的索引库 实践亲测有效!
PHP application docking justswap special development kit【 JustSwap.PHP ]
[self taught unity2d legendary game development] map editor
代码重构之法——方法重构分析
Call analysis of start method in JNI thread and callback analysis of run method
Event monitoring problem
Multi robot market share solution
Axios learning notes (2): easy to understand the use of XHR and how to package simple Axios
Share with Lianyun: is IPFs / filecoin worth investing in?
预留电池接口,内置充放电电路及电量计,迅为助力轻松搞定手持应用