入门 | egg.js 入门之egg-jwt
时间:2022-07-22
本文章向大家介绍入门 | egg.js 入门之egg-jwt,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
小小继续学习,这次学习的内容是egg-jwt 相关。
创建egg项目
这里创建一个egg新项目,这里使用的是ts模式。
npm init egg --type=ts
npm install
安装相关的包
这里创建并安装完成以后,需要再次初始化俩包,分别为egg-cors与egg-jwt token 生成的验证包
npm install egg-cors egg-jwt --save
配置相关插件
这里配置相关的插件
import { EggPlugin } from 'egg';
const plugin: EggPlugin = {
jwt: {
enable: true,
package: "egg-jwt"
},
cors: {
enable: true,
package: 'egg-cors',
}
};
export default plugin;
配置默认配置文件
config.jwt = {
secret: "123456"//自定义 token 的加密条件字符串
};
config.security = {
csrf: {
enable: false,
ignoreJSON: true
},
domainWhiteList: ['http://localhost:8080'],//允许访问接口的白名单
};
config.cors = {
origin:'*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH'
};
这里配置完成了相关的默认配置
在根目录声明any类型
这里需要在跟目录声明一个any类型,用于前后端发送相关的字符串参数。
import 'egg';
declare module 'egg' {
interface Application {
jwt: any;
}
}
配置相关路由
这里在app/router.ts 创建相关的路由
import { Application } from 'egg';
export default (app: Application) => {
const { controller, router, jwt } = app;
//正常路由
router.post('/admin/login', controller.admin.login);
/*
* 这里的第二个对象不再是控制器,而是 jwt 验证对象,第三个地方才是控制器
* 只有在需要验证 token 的路由才需要第二个 是 jwt 否则第二个对象为控制器
**/
router.post('/admin',jwt, controller.admin.index);
};
这里就配置完成了相关的路由。
编写路由对应的控制器
这里编写路由所对应的控制器
这个控制器在app/controller/home.ts 目录下
import { Controller } from 'egg';
export default class AdminController extends Controller {
// 验证登录并且生成 token
public async login() {
const { ctx ,app} = this;
//获取用户端传递过来的参数
const data = ctx.request.body;
// 进行验证 data 数据 登录是否成功
// .........
//成功过后进行一下操作
//生成 token 的方式
const token = app.jwt.sign({
username: data.username, //需要存储的 token 数据
//......
}, app.config.jwt.secret);
// 生成的token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1NjAzNDY5MDN9.B95GqH-fdRpyZIE5g_T0l8RgzNyWOyXepkLiynWqrJg
// 返回 token 到前端
ctx.body = token;
};
//访问admin数据时进行验证token,并且解析 token 的数据
public async index() {
const { ctx ,app} = this;
console.log(ctx.state.user);
/*
* 打印内容为:{ username : 'admin', iat: 1560346903 }
* iat 为过期时间,可以单独写中间件验证,这里不做细究
* 除了 iat 之后,其余的为当时存储的数据
**/
ctx.body = {code:0,msg:'验证成功'};
}
}
前端请求相匹配
这里只需要在前端的authorization字段里,添加相关的配置信息即可。
axios({
method: 'post',
url: 'http://127.0.0.1:7001/admin',
data: {
username: 'admin',
lastName: '123456'
},
headers:{
// 切记 token 不要直接发送,要在前面加上 Bearer 字符串和一个空格
'Authorization':`Bearer ${token}`
}
}).then(res=>{
console.log(res.data)
})
这里就完成了egg.js 结合jwt完成相关的验证
小tips
这里插曲一个小tips,这里使用的是jsonwebtoken。这里使用jsonwebtoken实现token相关认证机制。
安装
这里安装相关的依赖
npm install jsonwebtoken
编写中间件
在middleware文件下新建一个jwt.ts 文件
'use strict'
const fs = require('fs')
const path = require('path')
const jwt = require('jsonwebtoken') //引入jsonwebtoken
module.exports = (options, app) => {
return async function userInterceptor(ctx, next) {
let authToken = ctx.header.authorization // 获取header里的authorization
if (authToken) {
authToken = authToken.substring(7)
const res = verifyToken(authToken) // 解密获取的Token
if (res.corpid && res.userid) {
// 如果需要限制单端登陆或者使用过程中废止某个token,或者更改token的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效
// 此处使用redis进行保存
const redis_token = await app.redis.get('loginToken').get(res.corpid + res.userid) // 获取保存的token
if (authToken === redis_token) {
ctx.locals.corpid = res.corpid
ctx.locals.userid = res.userid
await next()
} else {
ctx.body = { code: 50012, msg: '您的账号已在其他地方登录' }
}
} else {
ctx.body = { code: 50012, msg: '登录状态已过期' }
}
} else {
ctx.body = { code: 50008, msg: '请登陆后再进行操作' }
}
}
}
// 解密,验证
function verifyToken(token) {
const cert = fs.readFileSync(path.join(__dirname, '../public/rsa_public_key.pem')) // 公钥,看后面生成方法
let res = ''
try {
const result = jwt.verify(token, cert, { algorithms: [ 'RS256' ] }) || {}
const { exp } = result,
current = Math.floor(Date.now() / 1000)
if (current <= exp) res = result.data || {}
} catch (e) {
console.log(e)
}
return res
}
使用中间件
这里在config.default.js中加入如下的配置,实现中间件的开启和配置
// 方法一:在应用中使用中间件
config.middleware = [ 'jwt' ]
config.jwt = {
enable: true,
ignore: [ '/api/v1/test/', '/public/' ], // 哪些请求不需要认证
}
// 方法二:router中使用中间件
module.exports = app => {
const jwt = app.middleware.jwt();
app.router.get('/api/v1/test/', jwt, app.controller.test.test);
};
token生成
这里卸载文件里,用于调用,生成相关的token
loginToken(data, expires = 7200) {
const exp = Math.floor(Date.now() / 1000) + expires
const cert = fs.readFileSync(path.join(__dirname, '../public/rsa_private_key.pem')) // 私钥,看后面生成方法
const token = jwt.sign({ data, exp }, cert, { algorithm: 'RS256' })
return token
}
调用相关的生成方法
const token = ctx.helper.loginToken({ corpid: usersData.corpid, userid: usersData.userid }, 7200) // token生成
await app.redis.get('loginToken').set(usersData.corpid + usersData.userid, token, 'ex', 7200) // 保存到redis
ctx.body = { data: { token, expires: this.config.login_token_time }, code: 1, msg: '登录成功' } // 返回前端
前端使用
这里前端使用headers,在后面加上相关的空格。
例:axios中
// request拦截器
service.interceptors.request.use(config => {
if (store.getters.token) {
config.headers['Authorization'] = `Bearer ${getToken()}`
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
这里就完成了相关jwt的生成与使用。
- WordPress 中部署真正的懒加载(Lazy Load)
- 图形化的2008R2 Server Core 配置管理工具
- 各种浏览器的userAgent
- WordPress 根据浏览器 user-agent 按需加载CSS 文件
- memcached的最新状态
- [程序设计语言]-01:引言
- ASP.NET Ajax 库
- ASP.NET进程优化
- 多说 提速:js内页页脚加载、静态文件CDN
- 微信小程序的王者时代
- [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)
- NUMA架构
- 如何处理 Python 入门难以进步的现象?
- 编写前置和后置条件的连贯接口库:CuttingEdge.Conditions
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- LeetCode25|二叉树的镜像
- 生成接口测试报告
- LeetCode24|第一个只出现一次的字符
- LeetCode27|最长公共前缀
- 搭建简易的物联网服务端和客户端-蓝牙控制(十六)
- java基础|CollectionUtils工具的基本使用
- LeetCode36|二叉树的右视图
- LeetCode35|完全二叉树的节点个数
- LeetCode34|数组中的第k个最大元素
- LeetCode33|寻找重复数
- LeetCode32|前k个高频元素
- LeetCode31|打印从1到最大的n位数
- LeetCode30|翻转单词顺序
- LeetCode28|最后一个单词的长度
- VS2015创建UWP报“vstemplate文件引用的向导类”错误