Koa 鉴权实战 - Token

简介: Koa 鉴权实战 - Token

Token 验证

session 不足:

  • 服务端有状态需要维护
  • 依赖 cookie ,APP 或 跨域处理复杂

JWT (JSON Web Token)

Bearer token 组成:Header、payload(载荷)、Signature(签名)
Header.Payload.Signature

  • Header:JSON 对象,描述 JWT 的元数据,用 Base64URL 算法转成字符串

    {
      "alg": "HS256", // 签名算法,默认是 HMAC SHA256(写成 HS256)
      "typ": "JWT" // Token 类型
    }
  • Payload: JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用,也可以定义私有字段。JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。使用 Base64URL 算法转成字符串

    字段名称 说明
    iss (issuer) 签发人
    exp (expiration time) 过期时间
    sub (subject) 主题
    aud (audience) 受众
    nbf (Not Before) 生效时间
    iat (Issued At) 签发时间
    jti (JWT ID) 编号
  • Signature:对前两部分的签名,防止数据篡改。签名密钥只有服务器知道

JWT 特点

  • JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次
  • JWT 不加密的情况下,不能将秘密数据写入 JWT
  • JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数
  • JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑
  • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证
  • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输

JWT 生效过程梳理

// jwt.js
const jsonwebtoken = require('jsonwebtoken');

// 签名密钥
const secret = 'hello';

// 数据
const user = {
  username: 'cell',
  password: 'pwd',
};

// 计算token
const token = jsonwebtoken.sign({
  data: user,
  exp: Math.floor(Date.now() / 1000) + (60 * 60),
}, secret);

console.log(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiY2VsbCIsInBhc3N3b3JkIjoicHdkIn0sImV4cCI6MTYxNTAzNDk3OCwiaWF0IjoxNjE1MDMxMzc4fQ.iZAHDN6a8eTBcB6a6reeNLgDD-tI9g7CBvfBh9b5Ivs

// 解算 验证
console.log('解码', jsonwebtoken.verify(token, secret));
// 解码 {
//   data: { username: 'cell', password: 'pwd' },
//   exp: 1615035042,
//   iat: 1615031442
// }

简单 token 使用流程

前端页面 index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">
  </script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
  <div id="app">
    <div>
      <input v-model="username">
      <input v-model="password">
    </div>
    <div>
      <button @click="login">Login</button>
      <button @click="logout">Logout</button>
      <button @click="getUser">Get User</button>
    </div>
    <div>
      <button @click="logs=[]">Clear Log</button>
    </div>
    <ul>
      <li v-for="(log, idx) in logs" :key="idx">{{log}}</li>
    </ul>
  </div>
  <script>
    axios.interceptors.request.use(config => {
      const token = window.localStorage.getItem('token');
      if (token) {
        // 如果 token 存在,在每个 HTTP header 都加上 token
        // Bearer 是 JWT 的认证头部信息
        config.headers.common['Authorization'] = `Bearer ${token}`;
      }
      return config;
    }, err => {
      return Promise.reject(err);
    });
    axios.interceptors.response.use(res => {
      app.logs.push(JSON.stringify(res.data));
      return res;
    }, err => {
      app.logs.push(JSON.stringify(err.data));
      return Promise.reject(err);
    });
    const app = new Vue({
      el: '#app',
      data: {
        username: 'cell',
        password: 'pwd',
        logs: [],
      },
      methods: {
        async login() {
          const res = await axios.post('/users/login-token', {
            username: this.username,
            password: this.password
          });
          localStorage.setItem('token', res.data.token);
        },
        async logout() {
          localStorage.removeItem('token');
        },
        async getUser() {
          await axios.get('/users/getUser-token');
        }
      }
    });
  </script>
</body>
</html>

服务端 index.js

const Koa = require('koa');
const router = require('koa-router')();

const jwt = require('jsonwebtoken');
const jwtAuth = require('koa-jwt');
const bodyParser = require('koa-bodyparser');
const static = require('koa-static');

const secret = 'my-secret';
const app = new Koa();
app.keys = ['my secret'];

app.use(static(__dirname + '/'));
app.use(bodyParser());

router.post('/users/login-token', async ctx => {
  const { body } = ctx.request;
  const userinfo = body.username;
  ctx.body = {
    message: 'Login Successful',
    user: userinfo,
    // 生成 token 返回给客户端
    token: jwt.sign({
      data: userinfo,
      exp: Math.floor(Date.now() / 1000) + 60 * 60, // 一小时后过期
    }, secret)
  };
});

router.get('/users/getUser-token',
  jwtAuth({
    secret
  }),
  async ctx => {
    // 验证通过
    console.log(ctx.state.user);
    // 获取 信息
    ctx.body = {
      message: 'Get Data Successful',
      userinfo: ctx.state.user.data
    };
});

app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
相关文章
|
Java Windows
JDK 1.8(Windows版)安装教程
JDK 1.8(Windows版)安装教程
452 1
|
区块链 算法 数据安全/隐私保护
带你读《区块链开发实战: 基于JavaScript的公链与DApp开发》之一:自己动手实现一个区块链系统
本书用三个部分讲解了区块链技术以及Asch的相关实践,第一部分讲解了区块链技术的基本概念,并用300行代码实现了一个最小的、可运行的区块链;第二部分分析Asch的源码,讲解Asch的实现原理;第三部分介绍了基于Asch的侧链技术的DApp开发实战。
|
6月前
|
JavaScript 前端开发 算法
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
数据采集 XML API
淘宝商品评论数据采集教程丨淘宝商品评论数据接口(Taobao.item_review)
**摘要:** 本教程指导如何使用淘宝(Taobao.item_review)接口采集商品评论。步骤包括注册开发者账号,创建应用获取API密钥,发送请求(如num_iid, page, size参数),解析JSON或XML返回数据,并遵循使用规则与安全注意事项。接口允许获取商品评论列表,含评论内容、评论者信息等,适用于数据分析和市场研究。务必保护API密钥并遵守使用政策。
|
9月前
|
JSON API 开发者
淘宝买家秀数据接口(taobao.item_review_show)丨淘宝 API 实时接口指南
淘宝买家秀数据接口(taobao.item_review_show)可获取买家上传的图片、视频、评论等“买家秀”内容,为潜在买家提供真实参考,帮助商家优化产品和营销策略。使用前需注册开发者账号,构建请求URL并发送GET请求,解析响应数据。调用时需遵守平台规定,保护用户隐私,确保内容真实性。
|
数据采集 Python
|
存储 人工智能 文字识别
极速搭建基于人工智能的OCR识别应用
本场景将使用阿里云函数计算,Serverless 应用中心,带大家 1分钟 Serverless 极速部署基于人工智能的OCR识别应用。
|
前端开发 应用服务中间件
前端项目部署问题总结
【7月更文挑战第13天】
167 1
|
数据采集 JSON API
淘宝商品评论数据采集教程丨淘宝商品评论数据接口Taobao.item_review
`淘宝开放平台的Taobao.item_review API让开发者能获取商品评论。步骤包括注册开发者账号,创建应用获取API密钥,理解和使用请求参数,签名验证并发送HTTP请求。返回的JSON数据包含评论详情,需解析并清洗后分析。注意频率限制和用户隐私保护。此接口助力商家分析用户反馈,优化经营策略。`