Rumah  >  Artikel  >  hujung hadapan web  >  Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

青灯夜游
青灯夜游ke hadapan
2022-10-28 19:37:291787semak imbas

Artikel ini akan bercakap dengan anda tentang prinsip pengesahan JWT bahagian belakang yang berkaitan dan cara menggunakannya dalam Node Saya harap ia akan membantu anda, terima kasih.

Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

[Cadangan tutorial berkaitan: tutorial video nodejs]

1. Mengapa menggunakan JWT

Kemunculan satu teknologi adalah untuk menebus kekurangan teknologi yang lain. Sebelum kemunculan JWT, mekanisme pengesahan Sesi perlu dilaksanakan dengan Cookie. Memandangkan Kuki tidak menyokong akses merentas domain secara lalai, apabila menyentuh permintaan merentas domain bahagian hadapan ke antara muka bahagian belakang, banyak konfigurasi tambahan diperlukan untuk mencapai sesi merentas domain pengesahan.

Nota:

  • Apabila bahagian hadapan meminta antara muka bahagian belakang dan tiada isu merentas domain, adalah disyorkan untuk menggunakan mekanisme pengesahan Sesi.
  • Apabila bahagian hadapan perlu meminta antara muka bahagian belakang merentas domain, tidak disyorkan untuk menggunakan mekanisme pengesahan Sesi Adalah disyorkan untuk menggunakan mekanisme pengesahan JWT.

2 Apakah itu JWT

JWT (nama bahasa Inggeris penuh: JSON Web Token) merupakan rancangan penyelesaian pengesahan merentas domain yang paling popular . Intipatinya ialah spesifikasi penulisan rentetan, seperti yang ditunjukkan di bawah, yang digunakan untuk memindahkan maklumat yang selamat dan boleh dipercayai antara pengguna dan pelayan

Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

Dalam proses pembangunan semasa bahagian hadapan dan pemisahan bahagian belakang , menggunakan mekanisme pengesahan

untuk pengesahan identiti ialah penyelesaian yang paling biasa adalah seperti berikut: token

    Apabila pelayan mengesahkan bahawa akaun pengguna dan kata laluan adalah betul, ia. mengeluarkan token kepada pengguna. Token ini Token digunakan sebagai bukti kelayakan untuk pengguna berikutnya untuk mengakses beberapa antara muka
  • Lawatan seterusnya akan menggunakan token ini untuk menentukan sama ada pengguna mempunyai kebenaran untuk mengakses

3. Prinsip kerja JWT

Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

Ringkasan: Maklumat pengguna disimpan dalam pelayar klien dalam bentuk rentetan Token. Pelayan mengesahkan identiti pengguna dengan

memulihkan rentetan Token.

4. Komponen token

dibahagikan kepada tiga bahagian, Pengepala, Muatan, Tandatangan dan Penggunaan Token untuk menyambung. Pengepala dan muatan menyimpan data dalam format ., tetapi dikodkan. Formatnya adalah seperti berikut: JSON

Header.Payload.Signature
Berikut ialah contoh rentetan JWT:

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjQ0ODI3NzI2LCJleHAiOjE2NDQ4Mjc3NTZ9.gdZKg9LkPiQZIgNAZ1Mn14GQd9kZZua-_unwHQoRsKE
Nota: Pembawa ialah maklumat pengepala yang ditambah secara manual, dan maklumat ini mesti dibawa untuk menghuraikan token!

5. Maksud tiga bahagian token

1. , di sini terutamanya mengisytiharkan algoritma yang digunakan. Nama medan untuk mengisytiharkan algoritma ialah , dan terdapat juga medan lalai ialah

. Algoritma dalam contoh berikut ialah HS256:

algtypOleh kerana JWT ialah rentetan, kita juga perlu mengekodkan kandungan di atas Rentetan yang dikodkan adalah seperti berikut: JWT

{ "alg": "HS256", "typ": "JWT" }

2. muatan

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Muatan ialah badan mesej Kandungan sebenar akan disimpan di sini, iaitu, pengisytiharan data , seperti dan , secara lalai. Dengan membawa masa pengeluaran token

, anda juga boleh menetapkan masa tamat tempoh, seperti berikut:

Tokenid Selepas pengekodan Base64 yang sama, rentetannya adalah seperti berikut: name iat

{ 
   "sub": "1234567890", 
   "name": "CoderBin", 
   "iat": 1516239022
}
3. Tandatangan

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
tandatangan adalah untuk menandatangani tajuk dan kandungan muatan Secara umumnya, tetapkan

dan lakukan algoritma pada dua hasil pertama . Formulanya adalah seperti berikut:

Setelah dua bahagian pertama data diusik, selagi kunci yang digunakan untuk penyulitan pelayan tidak bocor, tandatangan yang diperolehi pasti tidak konsisten dengan yang sebelumnya. tandatangan secretKeyHMACSHA25

6. Cara menggunakan JWT
Signature = HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey)

Selepas pelanggan menerima JWT yang dikembalikan oleh pelayan, ia biasanya menyimpannya dalam

atau .

Selepas itu, setiap kali pelanggan berkomunikasi dengan pelayan, ia mesti membawa rentetan JWT ini untuk pengesahan identiti. Pendekatan yang disyorkan ialah

meletakkan JWT dalam medan Kebenaran pengepala permintaan HTTP localStorage, dengan format berikut: sessionStorage

7. Pelaksanaan JWT

Authorization: Bearer <token></token>
Penggunaan

terbahagi kepada dua bahagian:

Jana token: Apabila log masuk berjaya, keluarkan token

TokenSahkan token: Apabila mengakses sumber tertentu atau antara muka, sahkan token

  • Seterusnya, saya akan membawa anda untuk melaksanakan pengesahan jwt dalam persekitaran
  • Akhirnya, terdapat kod lengkap dengan ulasan
  • 1. 安装 JWT 相关的包

    运行如下命令,安装如下两个 JWT 相关的包:

    npm i jsonwebtoken express-jwt

    其中:

    • jsonwebtoken 用于生成 JWT 字符串
    • express-jwt 用于验证token,将 JWT 字符串解析还原成 JSON 对象

    2. 导入 JWT 相关的包

    app.js

    // 导入用于生成 JWT 字符串的包
    const jwt = require('jsonwebtoken')
    
    // 导入用户将客户端发送过来的 JWT 字符串,解析还原成 JSON 对象的包
    const expressJWT = require('express-jwt')

    3. 定义 secret 密钥 *

    为了保证 JWT 字符串的安全性,防止 JWT 字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密解密的 secret 密钥:

    • 当生成 JWT 字符串的时候,需要使用 secret 密钥对用户的信息进行加密,最终得到加密好的 JWT 字符串

    • 当把 JWT 字符串解析还原成 JSON 对象的时候,需要使用 secret 密钥进行解密

    // 这个 secretKey 的是可以是任意的字符串
    const secretKey = 'CoderBin ^_^'

    4. 在登录成功后生成 JWT 字符串 *

    调用 jsonwebtoken 包提供的 sign() 方法,将用户的信息加密成 JWT 字符串,响应给客户端:

    • 参数 1:用户的信息对象
    • 参数 2:解密的秘钥
    • 参数 3:配置对象,可以配置 token 的有效期

    注意:千万不要把密码加密到 token 字符串中!

    // 登录接口
    app.post('/api/login', function (req, res) {
      // 将 req.body 请求体中的数据,转存为 userinfo 常量
      const userinfo = req.body
      // 省略登录失败情况下的代码... 
    
      // 登录成功
      // 在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
      const tokenStr = jwt.sign(
        { username: userinfo.username }, 
        secretKey, 
        { expiresIn: '30s' }
      )
      
      // 向客户端响应成功的消息
      res.send({
        status: 200,
        message: '登录成功!',
        token: tokenStr // 要发送给客户端的 token 字符串
      })
    })

    5. 将 JWT 字符串还原为 JSON 对象 *

    客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的 Authorization 字段,将 Token 字符串发送到服务器进行身份认证。

    此时,服务器可以通过 express-jwt 这个中间件,自动将客户端发送过来的 Token 解析还原成 JSON 对象:

    • express.JWT({ secret: secretKey, algorithms: ['HS256'] }) 就是用来解析 Token 的中间件
    • express-jwt 模块,现在默认为 6版本以上,必须加上: algorithms: ['HS256']

    注意:只要配置成功了 express-jwt 这个中间件,就会自动把解析出来的用户信息,挂载到 req.user 属性上

    // 1. 使用 app.use() 来注册中间件
    app.use(expressJWT({ 
      secret: secretKey, 
      algorithms: ['HS256'] 
    }).unless({ path: [/^\/api\//] }))

    注意

    • secret 必须和 sign 时候保持一致
    • 可以通过 unless 配置接口白名单,也就是哪些 URL 可以不用经过校验,像登陆/注册都可以不用校验
    • 校验的中间件需要放在需要校验的路由前面,无法对前面的 URL 进行校验

    6. 使用 req.user 获取用户信息

    当 express-jwt 这个中间件配置成功之后,即可在那些有权限的接口中,使用 req.user 对象,来访问从 JWT 字符串中解析出来的用户信息了,示例代码如下:

    // 这是一个有权限的 API 接口,必须在 Header 中携带 Authorization 字段,值为 token,才允许访问
    app.get('/admin/getinfo', function (req, res) {
      // TODO_05:使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端
      console.log(req.user);
      res.send({
        status: 200,
        message: '获取用户信息成功!',
        data: req.user // 要发送给客户端的用户信息
      })
    })

    7. 捕获解析 JWT 失败后产生的错误

    当使用 express-jwt 解析 Token 字符串时,如果客户端发送过来的 Token 字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行。我们可以通过 Express 的错误中间件,捕获这个错误并进行相关的处理,示例代码如下:

    app.use((err, req, res, next) => {
      // 这次错误是由 token 解析失败导致的
      if (err.name === 'UnauthorizedError') {
        return res.send({
          status: 401,
          message: '无效的token'
        })
      }
      res.send({
        status: 500,
        message: '未知的错误'
      })
    })

    8. 完整代码

    app.js

    // 导入 express 模块
    const express = require('express')
    // 创建 express 的服务器实例
    const app = express()
    
    // TODO_01:安装并导入 JWT 相关的两个包,分别是 jsonwebtoken 和 express-jwt
    const jwt = require('jsonwebtoken')
    const expressJWT = require('express-jwt')
    
    
    // 允许跨域资源共享
    const cors = require('cors')
    app.use(cors())
    
    // 解析 post 表单数据的中间件
    const bodyParser = require('body-parser')
    // 这里用内置的中间件也行: app.use(express.urlencoded({ extended: false }))
    app.use(bodyParser.urlencoded({ extended: false }))
    
    // TODO_02:定义 secret 密钥,建议将密钥命名为 secretKey
    // 这个 secretKey 的是可以是任意的字符串
    const secretKey = 'smiling ^_^'
    
    // TODO_04:注册将 JWT 字符串解析还原成 JSON 对象的中间件
    // 1. 使用 app.use() 来注册中间件
    // 2. express.JWT({ secret: secretKey, algorithms: ['HS256'] }) 就是用来解析 Token 的中间件
    // 2.1 express-jwt 模块,现在默认为 6版本以上,必须加上: algorithms: ['HS256']
    // 3. .unless({ path: [/^\/api\//] }) 用来指定哪些接口不需要访问权限
    // 4. 注意:只要配置成功了 express-jwt 这个中间件,就会自动把解析出来的用户信息,挂载到 req.user 属性上
    app.use(expressJWT({ secret: secretKey, algorithms: ['HS256'] }).unless({ path: [/^\/api\//] }))
    
    // 登录接口
    app.post('/api/login', function (req, res) {
      // 将 req.body 请求体中的数据,转存为 userinfo 常量
      const userinfo = req.body
      // 登录失败
      if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
        return res.send({
          status: 400,
          message: '登录失败!'
        })
      }
      // 登录成功
      // TODO_03:在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
      // 参数 1:用户的信息对象
      // 参数 2:解密的秘钥
      // 参数 3:配置对象,可以配置 token 的有效期
      // 记住:千万不要把密码加密到 token 字符串中!
      const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
      res.send({
        status: 200,
        message: '登录成功!',
        token: tokenStr // 要发送给客户端的 token 字符串
      })
    })
    
    // 这是一个有权限的 API 接口,必须在 Header 中携带 Authorization 字段,值为 token,才允许访问
    app.get('/admin/getinfo', function (req, res) {
      // TODO_05:使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端
      console.log(req.user);
      res.send({
        status: 200,
        message: '获取用户信息成功!',
        data: req.user // 要发送给客户端的用户信息
      })
    })
    
    // TODO_06:使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
    app.use((err, req, res, next) => {
      // 这次错误是由 token 解析失败导致的
      if (err.name === 'UnauthorizedError') {
        return res.send({
          status: 401,
          message: '无效的token'
        })
      }
      res.send({
        status: 500,
        message: '未知的错误'
      })
    })
    
    // 调用 app.listen 方法,指定端口号并启动web服务器
    app.listen(8888, function () {
      console.log('Express server running at http://127.0.0.1:8888')
    })

    八. 测试结果

    1 测试登录接口

    借助 postman 工具测试接口

    Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

    2. 测试登录需要权限的接口-失败

    Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

    3. 测试登录需要权限的接口-成功

    Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas)

    九、最后总结

    JWT鉴权机制有许多优点:

    • json具有通用性,所以可以跨语言
    • 组成简单,字节占用小,便于传输
    • 服务端无需保存会话信息,很容易进行水平扩展
    • 一处生成,多处使用,可以在分布式系统中,解决单点登录问题
    • 可防护CSRF攻击

    当然,不可避免的也有一些缺点:

    • Bahagian muatan hanya dikodkan, jadi ia hanya boleh digunakan untuk menyimpan maklumat tidak sensitif yang diperlukan untuk logik
    • Ia perlu untuk melindungi kunci penyulitan Sebaik sahaja ia bocor, akibatnya akan menjadi bencana
    • Untuk mengelakkan token dirampas, sebaiknya gunakan protokol https

    Analisis ringkas mekanisme pengesahan JWT ini berakhir di sini semua, terima kasih!

    Untuk lebih banyak pengetahuan berkaitan nod, sila lawati: tutorial nodejs!

Atas ialah kandungan terperinci Apa itu JWT? Bagaimana untuk melaksanakan mekanisme pengesahan JWT dalam Node (analisis ringkas). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam