egg-JWT的使用(服务端和客户端保存登录状态)

1.什么是JWT?

JSON Web Token(JWT)是一种客户端保存登录状态的解决方案
优点和使用redis保存登录状态一样, 能更好的支持分布式架构

2.JWT格式

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpZCI6NSwidXNlcm5hbWUiOiJ6aGFvbGl1IiwiZW1haWwiOm51bGwsInBob25lIjpudWxsLCJjcmVhdGVkQXQiOiIyMDIwLTA3LTIzVDA3OjEzOjUzLjAwMFoiLCJ1cGRhdGVkQXQiOiIyMDIwLTA3LTIzVDA3OjEzOjUzLjAwMFoiLCJpYXQiOjE1OTU0OTE5ODAsImV4cCI6MTU5NjA5Njc4MH0.
cQGJ72tEtBZdSWo9igyMTFI9V3mt07FfNEdZcNUAFZ8

Header 头部
Payload 负载
Signature 签名

例如: 现在JWT中保存的是张三, 那么当前的签名就是张三的指纹
      如果有人修改了JWT中保存的数据, 例如修改成了李四
      将来如果拿着李四和张三的指纹进行匹配, 那么就不匹配, 那么就怎么有人篡改了数据

https://jwt.io/

3.JWT弊端

- JWT 的最大缺点是,由于服务器不保存登录状态,因此无法在使用过程中废止某个
  登录状态,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前
  就会始终有效,除非服务器部署额外的逻辑。
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了
  减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应 
  该再次对用户进行认证。
- 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

4.使用JWT
4.1 安装JSON Web Token

npm install jsonwebtoken

4.2 如何使用JWT

- 服务端生成jwt令牌,发送给客户端
- 客户端将令牌保存到cookie或者sessionStorage、localStorage中
- 客户端每次发送请求将令牌一并发送到服务端
- 服务端通过密钥验证令牌

4.3 服务端生成jwt令牌

 const jwt = require('jsonwebtoken');
  public async index() {
    const { ctx } = this;
    try {
      // 1.校验数据和验证码
      this.validateUserInfo();
      const data = ctx.request.body;
      ctx.helper.verifyImageCode(data.captcha);
      // 2.将校验通过的数据保存到数据库中
      const user = await ctx.service.user.getUser(data);
      delete user.password;
      // ctx.session.user = user;
      // 3.生成JWT令牌
      // 第一个参数: 需要保存的数据
      // 第二个参数: 签名使用的密钥 这里使用this.config.keys
      // 第三个参数: 额外配置 比如expiresIn过期时间
      const token = jwt.sign(user, this.config.keys, { expiresIn: '7 days' });
      user.token = token;
      ctx.success(user);
    } catch (e:any) {
      if (e.errors) {
        ctx.error(400, e.errors);
      } else {
        ctx.error(400, e.message);
      }
    }
  }

4.4 客户端将令牌保存到sessionStorage

 loginUser(this.loginData)
            .then((data:any)=>{
              if(data.code === 200){
                /*
                cookie: 如果存储的内容体积不大
                sessionStorage: 如果不需要持久化存储
                localStorage: 如果体积较大, 又需要持久化存储
                * */
                sessionStorage.setItem('token', data.data.token);
                this.$router.push('/admin');
              }else{
                (this as any).$message.error(data.msg);
              }
            })
            .catch((e)=>{
              (this as any).$message.error(e.message);
            });

4.5 客户端每次发送请求将令牌一并发送到服务端
配置客户端网络文件api/network.ts

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
//客户端每次发送请求将令牌一并发送到服务端
    (config.headers as any).Authorization = sessionStorage.getItem('token');
    // 在发送请求之前做些什么
    return config
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error)
})

4.5 服务端通过密钥验证令牌

  public async isLogin() {
    const { ctx } = this;
    const token = ctx.get('Authorization');
    try {
      // 第一个参数: 需要校验的token
      // 第二个参数: 当初加密的密钥
      const user = jwt.verify(token, this.config.keys);
      ctx.success(user);
    } catch (e:any) {
      ctx.error(400, e.message);
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值