Apa itu JWT? Artikel ini akan membawa Anda untuk memahami JWT, memperkenalkan penerapan JWT di node, serta kelebihan dan kekurangan JWT, semoga bermanfaat bagi semuanya!
JWT adalah singkatan dari JSON Web Token , yang merupakan solusi otentikasi dalam lingkungan aplikasi jaringan, dalam mekanisme otentikasi tradisional, tidak lebih dari langkah-langkah berikut:
1. Pengguna mengirimkan kata sandi akun ke server; 2. Setelah server memverifikasi kata sandi akun, server akan menyimpan beberapa informasi terkait pengguna, peran pengguna atau waktu kedaluwarsa, dll. di sesi saat ini; 3. Server memberikan session_id kepada pengguna dan menuliskannya ke dalam cookie pengguna atau klien menyimpannya secara lokal; 4. Setiap kali pengguna meminta layanan, dia perlu membawa session_id ini, mungkin melalui cookie atau metode lain; 5. Setelah server menerimanya, server kembali ke database untuk menanyakan session_id saat ini dan memverifikasi apakah pengguna memiliki izin;
Keuntungan dari model ini adalah server dapat menghentikan izin pengguna kapan saja, dan dapat masuk ke database untuk mengubah atau menghapus informasi sesi pengguna saat ini. Namun ada juga kelemahannya, yaitu jika merupakan cluster server, semua mesin perlu berbagi informasi sesi untuk memastikan bahwa setiap server dapat memperoleh informasi penyimpanan sesi yang sama. Meskipun masalah-masalah ini dapat diselesaikan, namun jumlah pekerjaannya sangat besar.
Keuntungan dari solusi JWT adalah informasi ini tidak disimpan. Data token disimpan di klien. Setiap kali permintaan diterima, hanya perlu diverifikasi.
Mari kita bicara secara singkat tentang prinsip JWT. Faktanya, ketika klien mengirimkan permintaan otentikasi, server akan menghasilkan objek JSON setelah mengautentikasi pengguna, yang mungkin berisi informasi seperti "siapa Anda, apa yang Anda lakukan, dll. ., masa kadaluarsa ", yang penting harus ada masa kadaluwarsanya; format umumnya adalah:
{ nama pengguna: "string pencuri er", peran: "Petani Kode Dunia", waktu berakhir: "20 Mei 2022" }
Tapi itu tidak akan diteruskan kepada Anda dengan cara yang dangkal. Itu akan ditandatangani dan dikirim melalui algoritma tanda tangan yang dapat dibalik berdasarkan algoritma tanda tangan yang ditentukan dan beberapa informasi tentang muatan yang Anda kirimkan :
Seperti terlihat dari gambar, informasi yang dikembalikan secara kasar dibagi menjadi tiga bagian, sisi kiri adalah hasil setelah penandatanganan, yang merupakan hasil yang dikembalikan ke klien. Sisi kanan juga merupakan kode sumber yang didekodekan dipisahkan oleh "titik", masing-masing. Ada korespondensi satu-satu antara tiga warna merah, ungu dan cyan:
Bagian merah pertama adalah Header. Header terutama menentukan metode. Algoritma tanda tangan pada gambar ( default HS256 ) adalah HMAC dengan SHA-256. Ini adalah algoritma simetris. Hanya satu kunci yang dibagikan antara kedua pihak, ketik The pengidentifikasi bidang bertipe JWT;
Bagian ungu kedua, payload, adalah objek JSON, yang merupakan data aktual yang akan dikirim. Ada tujuh field resmi yang dapat digunakan:
iss (penerbit): penerbit
exp (waktu kedaluwarsa): waktu kedaluwarsa
sub (mata pelajaran): mata pelajaran
aud (penonton): penonton
nbf (Tidak Sebelumnya): Waktu efektif
iat (Diterbitkan Pada): waktu penerbitan
jti (ID JWT): nomor
Selain kolom ini, Anda juga dapat membuat beberapa kolom khusus. Karena JWT tidak dienkripsi secara default, berhati-hatilah untuk tidak menggunakan beberapa data sensitif saat menggunakannya.
Bagian ketiga adalah tanda tangan Signature
. Bagian ini adalah kunci rahasia yang Anda tentukan dan hanya ada di server, dan kemudian menggunakan algoritma yang ditentukan di header untuk menandatangani melalui metode tanda tangan berikut.
Mari kita alami penggunaan spesifiknya di bawah ini:
Langkah 1: Kita perlu membangun proyek nodejs; menginisialisasi proyek melalui npm init -y
; kemudian kita perlu menginstal dependensi, termasuk express
, jsonwebtoken
dan nodemon
:
$npm saya mengekspresikan jsonwebtoken nodemon
Kemudian tambahkan perintah nodemon app.js
pada kolom scripts
di package.json
:
"skrip": { "mulai": "nodemon app.js" },
Langkah 2: Inisialisasi aplikasi node dan buat file app.js di direktori root;
// aplikasi.js const express = memerlukan("ekspres"); aplikasi const = ekspres(); aplikasi.menggunakan(express.json()); aplikasi.dengarkan(3000, () => { console.log(3000 + "mendengarkan..."); // Dengarkan port 3000});
Langkah 3: Perkenalkan ketergantungan jsonwebtoken
dan buat kunci pribadi antarmuka dan server;
// aplikasi.js //... const jwt = memerlukan("jsonwebtoken"); const jwtKey = "~!@#$%^&*()+,"; // ...
jwtKey
di sini adalah kunci pribadi khusus kami yang hanya disimpan di server. Setelah itu, kami mulai menulis antarmuka /login untuk masuk, dan membuat database simulasi lokal untuk verifikasi, dan melakukannya melalui metode jwt.sign
. Verifikasi tanda tangan:
// aplikasi.js basis data konstan = { nama pengguna: "nama pengguna", kata sandi: "kata sandi", }; app.post("/login", (permintaan, res) => { const { nama pengguna, kata sandi } = req.body; if (nama pengguna === database.nama pengguna && kata sandi === database.kata sandi) { jwt.tanda( { nama belakang, }, jwtKey, { kedaluwarsaDalam: "30S", }, (_, tanda) => { res.json({ nama belakang, pesan : “Login berhasil”, token, }); } ); } });
Dalam kode di atas, kami membuat variabel database
untuk mensimulasikan pembuatan akun lokal dan database kata sandi untuk memverifikasi login; kemudian kami membuat antarmuka post
/login
. Setelah memverifikasi bahwa akun dan kata sandi benar-benar cocok, kami mengimpornya melalui jsonwebtoken
paket. Gunakan metode sign
di bawah objek jwt
untuk menandatangani.
tanda fungsi ekspor( muatan: string |.Penyangga |. secretOrPrivateKey: Rahasia, pilihan?: Opsi Tanda, ): rangkaian; tanda fungsi ekspor( muatan: string |.Penyangga |. secretOrPrivateKey: Rahasia, panggilan balik: Panggilan Balik, ): ruang kosong; tanda fungsi ekspor( muatan: string |.Penyangga |. secretOrPrivateKey: Rahasia, pilihan: Opsi Tanda, panggilan balik: Panggilan Balik, ): ruang kosong;
Metode kelebihan object
digunakan di sini untuk mengimplementasikan antarmuka. Kami akan mengimplementasikan tanda tangan antarmuka terakhir di sini. Parameter pertama dapat berupa tipe objek khusus, tipe Buffer
, atau tipe string
secara langsung dan menyesuaikan beberapa bidang, karena JWT juga akan menandatangani data ini saat penandatanganan. Namun, perlu dicatat bahwa Anda harus mencoba untuk tidak menggunakan data sensitif di sini karena JWT tidak dienkripsi secara default belum diutak-atik, dan proses pengecekan tanda tangan disebut verifikasi .
Tentu saja, Anda juga dapat mengenkripsi Token asli dan kemudian mengirimkannya;
Parameter kedua: adalah kunci rahasia yang kami simpan di server untuk penandatanganan. Biasanya dalam mode klien-server, JWS menggunakan algoritma HS256 yang disediakan oleh JWA plus kunci. beberapa layanan mungkin perlu memverifikasi JWT. Jika kunci disimpan di setiap layanan, keamanannya akan sangat berkurang. Anda harus tahu bahwa setelah kunci bocor, siapa pun dapat memalsukan JWT sesuka hati.
Parameter ketiga: adalah opsi tanda tangan SignOptions
, tanda tangan antarmuka:
ekspor antarmuka SignOptions { algoritma?: Algoritma |. keyid?: string |.tidak terdefinisi; kadaluwarsa?: string |.nomor |. /** dinyatakan dalam detik atau string yang menjelaskan rentang waktu [zeit/ms](https://github.com/zeit/ms.js Misalnya: 60, "2 hari", "10 jam", "7 hari". */ tidakSebelum?: string |.nomor |. penonton?: string |. string[] |. subjek?: string |. penerbit?: string |.tidak terdefinisi; jwtid?: string |.tidak terdefinisi; mutatePayload?: boolean |. tidak ada stempel waktu?: boolean |. tajuk?: JwtHeader |. pengkodean?: string |. }
Di sini kami menggunakan kolom expiresIn
untuk menentukan waktu penuaan. Silakan lihat dokumen ini untuk metode penggunaan;
Parameter keempat adalah callback. Parameter kedua dari callback adalah token
yang kita hasilkan melalui tanda tangan. Terakhir, token
ini dikembalikan ke front end sehingga dapat disimpan secara lokal di front end dan dibawa ke server untuk verifikasi. pada setiap permintaan.
Selanjutnya, mari kita verifikasi antarmuka ini: Saya menginstal plug-in REST Client di vscode, lalu membuat file request.http
di direktori root, dan menulis informasi yang diminta di file:
POSTING http://localhost:3000/login tipe konten: aplikasi/json { "nama pengguna": "nama pengguna", "kata sandi": "kata sandi" }
Kemudian jalankan perintah npm run start
pada baris perintah untuk memulai layanan, lalu klik tombol Send Request
di atas file requset.http
untuk mengirim permintaan:
Setelah permintaan berhasil, Anda akan melihat pesan respons seperti ini:
Bidang token
adalah token
yang dihasilkan oleh JWT kami;
Mari kita verifikasi apakah token
ini valid. Kami sedang menulis antarmuka setelah login:
app.get("/afterlogin", (permintaan, res) => { const { header } = persyaratan; const token = header["otorisasi"].split(" ")[1]; //Letakkan token di kolom otorisasi header jwt.verify(token, jwtKey, (err, payload) => { jika (err) kembalikan res.sendStatus(403); res.json({ pesan: "Otentikasi berhasil", payload }); }); });
Dalam kode ini, token
yang sebelumnya dihasilkan melalui JWT diperoleh dengan mendapatkan token
di kolom authorization
di header permintaan. Kemudian verifikasi apakah token
tersebut valid dengan memanggil metode verifikasi jwt.verify
. Metode ini memiliki tiga parameter:
// Ada empat tanda tangan antarmuka, Anda dapat memeriksa sendiri dokumentasinya fungsi ekspor verifikasi( tanda: tali, //Token yang perlu diperiksa rahasiaOrPublicKey: Rahasia |.GetPublicKeyOrSecret, // Kunci tanda tangan yang ditentukan pada panggilan balik server?: VerifyCallback<JwtPayload |. // Callback untuk mendapatkan informasi hasil verifikasi): void;
Selanjutnya, kami menyalin token
yang baru saja kami tanggapi ke dalam header permintaan:
### DAPATKAN http://localhost:3000/afterlogin otorisasi: Pembawa eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwiaWF0IjoxNjUyNzg5NzA3LCJleHAiOjE2NTI3ODk3Mzd9.s9fk3YLhxTUcpUgCfIK4xQ N58 Hk_XEP5y9GM9A8jBbY
Otentikasi Bearer sebelumnya adalah metode otentikasi standar dalam protokol http.
Klik juga Send Request
dan ketika Anda melihat respon pada gambar di bawah ini berarti respon berhasil:
Sebenarnya di atas adalah beberapa kegunaan sederhana JWT. Selanjutnya mari kita bahas kelebihan dan kekurangan JWT itu sendiri.
Ruang penyimpanan yang ditempati JWT sebenarnya tidak sedikit. Jika kita perlu menandatangani terlalu banyak informasi, kemungkinan besar token akan melebihi batas panjang cookie.
Jelasnya, seiring dengan bertambahnya jumlah informasi dalam payload, panjang token juga akan bertambah;
Keamanan sebenarnya jika token
memakan terlalu banyak ruang, ruang penyimpanan maksimum Cookie
hanya 4kb. Front end dapat disimpan di penyimpanan lokal seperti localStorage
, tetapi akan menimbulkan masalah jika tidak ditempatkan dalam cookie, keamanannya akan sangat berkurang. Akan ada risiko mendapatkannya melalui skrip js, yang berarti peretas mana pun dapat melakukan apa saja dengannya;
Ketepatan waktu yang tidak fleksibel. Faktanya, aspek tertentu dari JWT adalah bahwa token
pengguna tidak perlu disimpan secara terus-menerus. Sebaliknya, token
diverifikasi secara efektif menggunakan verifikasi server waktu kedaluwarsa diubah, token
akan dirusak. Karena tidak ada cara untuk menyimpan dan mengubah tanggal kedaluwarsa secara manual, sulit untuk segera menghapus token
. Jika pengguna masuk dua kali dan dua token
dibuat, maka masuk prinsipnya, dua token
akan dihasilkan.
Hal di atas terutama berbicara tentang beberapa poin:
Prinsip JWT terutama menggunakan kunci pribadi server untuk berkomunikasi dengan token
yang dihasilkan oleh tanda tangan JSON;
Ini juga memperkenalkan komposisi data internal JWT, yang digunakan oleh Header untuk menentukan algoritma dan jenis tanda tangan, payload untuk mengirimkan data JSON, dan Signature untuk melakukan algoritma tanda tangan pada data dan mencegah gangguan;
Pengenalan rinci diberikan tentang cara menggunakan JWT melalui nodejs, melakukan penandatanganan data melalui metode sign
, dan melakukan verifikasi tanda tangan melalui metode verify
;
Beberapa kelemahan JWT juga diperkenalkan:
Salah satunya adalah ruang penyimpanan bertambah seiring dengan bertambahnya jumlah data tanda tangan;
Lalu ada keamanan, jika ruang penyimpanan terlalu besar tidak akan disimpan dalam Cookie
dengan tingkat keamanan yang relatif tinggi sehingga menyebabkan script diperoleh sesuka hati;
Lalu ada ketepatan waktu, yang tidak dapat secara fleksibel mengontrol ketepatan waktu token
;
Ini adalah kode sumber demo nodejs di atas untuk referensi;