Plug-in jwt-logout menggunakan Redis untuk mengimplementasikan manajemen state lemah pada JSON Web Tokens (JWT). Plug-in ini menyelesaikan masalah ketidakmampuan JWT mendukung logoff proaktif. Anda juga dapat menggunakannya untuk menerapkan fitur logon perangkat tunggal sebuah akun, di mana akun otomatis keluar dari perangkat saat digunakan untuk logon ke perangkat lain.
Jenis Plug-in
Plug-in untuk autentikasi dan otorisasi.
Bidang
Bidang | Tipe data | Diperlukan | Nilai default | Deskripsi |
jwks | string | Tidak | - | String JSON yang digunakan untuk memverifikasi JWT. Saat Anda menggunakan plug-in ini bersama dengan plug-in jwt-auth, Anda tidak perlu mengonfigurasi bidang ini. Untuk informasi lebih lanjut, lihat JSON Web Key (JWK). |
clock_skew | number | Tidak | 60 | Offset waktu yang diizinkan saat memeriksa bidang exp dan iat dalam JWT. Unit: detik. |
token_header | string | Tidak | Authorization | Header permintaan dari mana Anda dapat mengekstrak JWT. |
token_prefix | string | Tidak | "Bearer" | Prefiks nilai dalam header permintaan. Setelah prefiks dihapus, bagian sisanya dari header permintaan digunakan sebagai konten JWT. |
redis | Redis | Ya | - | Konfigurasi layanan Redis. |
logout | Logout | Tidak | - | Konfigurasi yang digunakan untuk mengimplementasikan fitur logoff JWT. Jika bidang ini tidak dikonfigurasi, fitur logoff JWT dinonaktifkan. |
login | Login | Tidak | - | Konfigurasi yang digunakan untuk mengimplementasikan fitur logon perangkat tunggal JWT. Jika bidang ini tidak dikonfigurasi, fitur logon perangkat tunggal JWT dinonaktifkan. |
Tabel berikut menjelaskan bidang konfigurasi tipe Redis.
Bidang | Tipe data | Diperlukan | Nilai default | Deskripsi |
service | string | Ya | - | Nama layanan Redis. Contoh:
|
port | number | Ya | - | Nomor port layanan Redis. |
username | string | Tidak | - | Nama pengguna yang digunakan dalam perintah AUTH Redis. |
password | string | Tidak | - | Kata sandi yang digunakan dalam perintah AUTH Redis. |
timeout | number | Tidak | 1000 | Periode timeout perintah Redis. Unit: milidetik. |
Tabel berikut menjelaskan bidang konfigurasi tipe Logout.
Bidang | Tipe data | Diperlukan | Nilai default | Deskripsi |
key_prefix | string | Tidak | higress_jwt_logout_ | Prefiks kunci yang disimpan di Redis. |
key | array of string | Tidak | ["jti"] | Kunci dalam payload JWT untuk mengidentifikasi JWT. Jika kunci yang sama terdapat dalam payload beberapa JWT, JWT tersebut dianggap sama. Jika kunci tidak terdapat dalam payload JWT, kesalahan 401 invalid token dilaporkan. |
path | string | Tidak | /jwt_logout | String karakter yang digunakan untuk mencocokkan akhiran jalur URL. Jika akhiran jalur URL cocok dengan string yang ditentukan, akun yang menggunakan JWT dalam permintaan saat ini akan keluar. JWT tidak dapat digunakan lagi. |
error_status | number | Tidak | 401 | Kode kesalahan yang dikembalikan saat logoff. |
error_body | string | Tidak | '{"message":"invalid token"}' | Badan respons saat logoff. |
ttl | number | Tidak | - | Waktu hidup (TTL) kunci yang disimpan di Redis. Unit: detik. Konfigurasi ini menentukan durasi di mana JWT menjadi tidak valid setelah logoff. Jika konfigurasi ini tidak ditentukan, TTL sama dengan nilai bidang exp dalam payload dikurangi waktu saat ini. Jika payload tidak berisi bidang exp, TTL default adalah 86.400 detik (24 jam). |
Tabel berikut menjelaskan bidang konfigurasi tipe Login.
Bidang | Tipe data | Diperlukan | Nilai default | Deskripsi |
key_prefix | string | Tidak | higress_jwt_logout_ | Prefiks kunci yang disimpan di Redis. |
key | array of string | Tidak | ["iss","aud","sub"] | Pengenal logon perangkat tunggal dalam payload JWT. Jika payload JWT dalam permintaan saat ini berisi bidang yang sama tetapi JWT permintaan tidak persis sama dengan JWT logon sukses, sistem menganggap permintaan saat ini sebagai permintaan logon ulang dan menolak permintaan tersebut. Sistem mengizinkan permintaan hingga kunci JWT untuk logon sukses di Redis kedaluwarsa. Jika payload JWT dalam permintaan saat ini tidak berisi bidang tersebut, kesalahan 401 invalid token dilaporkan. |
path | string | Tidak | /jwt_login | String karakter yang digunakan untuk mencocokkan akhiran jalur URL. Jika akhiran jalur URL cocok dengan string yang ditentukan, akun dipaksa logon ke sistem menggunakan JWT dalam permintaan saat ini. JWT yang digunakan untuk logon sukses dan memiliki karakteristik payload yang sama menjadi tidak valid saat logoff. |
error_status | number | Tidak | 403 | Kode kesalahan yang dikembalikan untuk logon ulang. |
error_body | string | Tidak | '{"message":"already login on other device"}' | Badan respons untuk logon ulang. |
ttl | number | Tidak | - | TTL kunci yang disimpan di Redis. Unit: detik. Bidang ini menentukan periode validitas JWT yang digunakan untuk logon perangkat tunggal. Jika bidang ini tidak ditentukan, TTL sama dengan nilai bidang exp dalam payload dikurangi waktu saat ini. Jika payload tidak berisi bidang exp, TTL default adalah 86.400 detik (24 jam). |
Contoh konfigurasi
Menggunakan instance ApsaraDB for Redis
Buat instance ApsaraDB for Redis. Untuk informasi lebih lanjut, lihat Ikhtisar.
Aktifkan konfigurasi logoff dan logon. Saat plug-in memproses permintaan, satu permintaan baca Redis untuk pemeriksaan konfigurasi logoff dan dua permintaan baca Redis untuk pemeriksaan konfigurasi logon dihasilkan. Dalam kasus langka seperti logoff atau logon pertama kali, dua permintaan tulis Redis tambahan dihasilkan. Untuk memperkirakan kapasitas instance ApsaraDB for Redis, Anda dapat mengalikan throughput permintaan yang diproses oleh plug-in dengan 2.
Setelah mengonfigurasi instance ApsaraDB for Redis, dapatkan titik akhir VPC dari instance tersebut. Contoh: r-xxxxxxx.redis.rds.aliyuncs.com.
Tambahkan layanan. Pilih DNS Domain Name dari daftar drop-down Sumber Layanan, masukkan nomor port Redis (6379 dalam banyak kasus) di bidang Port Layanan, masukkan titik akhir VPC di bidang Nama Domain, dan pilih Dinonaktifkan dari daftar drop-down TLS Mode. Untuk informasi lebih lanjut, lihat Buat Layanan.
Tambahkan konten berikut ke konfigurasi plug-in untuk terhubung ke instance ApsaraDB for Redis:
redis: service: redis.dns port: 6379Jika Anda mengonfigurasi kata sandi untuk layanan Redis, tambahkan konten berikut:
redis: service: redis.dns port: 6379 password: ****** # Masukkan kata sandi yang Anda tentukan.
Mengimplementasikan fitur logoff JWT
Skenario penggunaan
JWT adalah token tanpa status. Jika JWT diterbitkan, itu valid hingga kadaluwarsa. Anda dapat menggunakan plug-in jwt-logout untuk menerapkan logoff paksa saat JWT tertentu digunakan.
Cara kerjanya
Jika akhiran jalur permintaan cocok dengan path dalam konfigurasi plug-in, mekanisme logoff dipicu. Instance ApsaraDB for Redis mencatat JWT untuk logoff. Kunci yang disimpan dalam instance ApsaraDB for Redis terdiri dari prefiks yang dikonfigurasi dan kunci serta nilai yang diekstraksi dari payload JWT saat ini.
Jika payload JWT yang dibawa dalam permintaan cocok dengan karakteristik kunci yang disimpan dalam instance ApsaraDB for Redis, sistem menganggap JWT saat ini tidak valid dan menolak permintaan.
Waktu kedaluwarsa default kunci yang disimpan dalam instance ApsaraDB for Redis dihitung berdasarkan bidang
expdalam payload JWT. Ini berarti kunci dapat disimpan hingga JWT kadaluwarsa.
Kunci logoff yang direkomendasikan default plug-in adalah ["jti"], di mana
jtiadalah bidang payload yang secara unik mengidentifikasi JWT. Seperti yang ditentukan dalam standar JWT, jika nilaijtidalam payload JWT sama dengan yang dicatat dalam instance ApsaraDB for Redis, seluruh JWT persis sama. Oleh karena itu, jti dapat digunakan untuk menandai status logoff JWT.Aturan penggabungan kunci yang disimpan dalam instance ApsaraDB for Redis:
<key_prefix><PayloadKey>##<PayloadValue>. PayloadKey adalah daftar kunci yang dipisahkan oleh tanda pagar (#). PayloadValue adalah daftar nilai kunci yang dipisahkan oleh tanda pagar (#). Contoh:higress_jwt_logout_jti#iss##xxxxx#abcde.Plug-in ini hanya dapat membuat token yang dibawa dalam permintaan saat ini tidak valid selama logoff. Anda juga dapat secara manual menentukan token di konsol ApsaraDB for Redis berdasarkan aturan penggabungan kunci sebelumnya. Jika gateway menemukan bahwa kunci ada dalam instance ApsaraDB for Redis, gateway menolak permintaan akses yang didasarkan pada JWT terkait.
Contoh
Konfigurasi plug-in:
redis:
service: redis.dns
port: 6379
jwks: |
{
"keys": [
{
"kty": "oct",
"kid": "123",
"k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
"alg": "HS256"
}
]
}
logout:
path: "/jwt_logout"
key: ["jti"]
error_status: 401
error_body: |
{"message":"invalid token"}Picu logoff.
curl http://xxx.hello.com/test/jwt_logout -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsInN1YiI6InRlc3QiLCJhdWQiOiJ3d3cudGVzdC5jb20iLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.tmKF6qc1mOWNyCCzBOT2XKNoEGeEgr3EbhTKAQfq1io' # Hasil berikut dikembalikan: {"message": "logout success"}Payload token:
{ "jti": "xxxx", "iss": "abcd", "sub": "test", "aud": "www.test.com", "iat": 1665660527, "exp": 1865673819 }Dalam kasus ini, kunci
higress_jwt_logout_jti##xxxxdisimpan dalam instance ApsaraDB for Redis.Setelah logoff, akses berdasarkan JWT tidak diizinkan.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsInN1YiI6InRlc3QiLCJhdWQiOiJ3d3cudGVzdC5jb20iLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.tmKF6qc1mOWNyCCzBOT2XKNoEGeEgr3EbhTKAQfq1io' # Hasil berikut dikembalikan: {"message":"invalid token"}
Menerapkan logoff paksa berdasarkan JWT
Skenario penggunaan
Ketika sebuah akun digunakan untuk logon ke beberapa perangkat dan autentikasi JWT digunakan untuk logon, JWT yang berbeda mungkin diterbitkan pada perangkat yang berbeda. Dalam hal ini, Anda dapat menggunakan plug-in jwt-logout untuk memungkinkan akun hanya logon ke satu perangkat pada satu waktu.
Cara kerjanya
Saat permintaan dimulai, sistem mengekstrak JWT dari permintaan saat ini dan membentuk kunci Redis berdasarkan prefiks yang dikonfigurasi serta kunci dan nilai yang diekstraksi dari payload JWT saat ini. Kemudian, sistem memeriksa nilai yang sesuai dengan kunci dalam instance ApsaraDB for Redis. Jika nilainya tidak konsisten dengan nilai kunci JWT saat ini, sistem menolak permintaan akses.
Jika nilai tidak ada, JWT saat ini ditulis ke kunci Redis. Waktu kedaluwarsa default kunci dalam instance ApsaraDB for Redis dihitung berdasarkan bidang
expdalam payload JWT. Ini berarti kunci dapat disimpan hingga JWT kadaluwarsa. Selama periode validitas JWT, permintaan akses berdasarkan JWT lain dengan karakteristik payload yang sama tidak diizinkan.Jika akhiran permintaan cocok dengan
pathdalam konfigurasi plug-in, mekanisme logoff paksa dipicu dan JWT saat ini ditulis ke nilai kunci Redis terkait. JWT yang digunakan untuk logon sukses dan memiliki karakteristik payload yang sama menjadi tidak valid saat logoff. Ini memastikan logon perangkat tunggal.
Kunci logon yang direkomendasikan default plug-in adalah ["iss","aud","sub"]. Dalam kunci tersebut,
issmenunjukkan penerbit JWT,audmenunjukkan skenario penggunaan JWT, dansubmenunjukkan subjek JWT. Dalam banyak kasus, kombinasi ini dapat digunakan untuk memastikan logon perangkat tunggal.Aturan penggabungan kunci yang disimpan dalam instance ApsaraDB for Redis:
<key_prefix><PayloadKey>##<PayloadValue>. PayloadKey adalah daftar kunci yang dipisahkan oleh tanda pagar (#). PayloadValue adalah daftar nilai kunci yang dipisahkan oleh tanda pagar (#). Contoh:higress_jwt_login_iss#aud#sub##xxxxx#abcde#fffff.Untuk JWT dengan karakteristik payload yang sama, JWT pertama yang digunakan untuk permintaan secara otomatis ditulis ke instance ApsaraDB for Redis. Ini membantu mengimplementasikan fitur logon perangkat tunggal plug-in. Oleh karena itu, Anda tidak perlu memanggil operasi API untuk logon paksa. Anda hanya perlu memanggil operasi API ketika logoff paksa diperlukan dalam skenario logon.
Saat Anda memicu logika logoff, kunci logon JWT saat ini yang disimpan dalam instance ApsaraDB for Redis dibersihkan. Aturan ini juga berlaku saat Anda mengaktifkan fitur logoff JWT.
Contoh
Konfigurasi plug-in:
redis:
service: redis.dns
port: 6379
jwks: |
{
"keys": [
{
"kty": "oct",
"kid": "123",
"k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
"alg": "HS256"
}
]
}
login:
path: "/jwt_login"
key: ["iss","aud","sub"]
error_status: 403
error_body: |
{"message":"already login on other device"}Lakukan operasi logon sukses.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ6enp6IiwiaXNzIjoiYWJjZCIsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6InRlc3QiLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.WljMr5ucxfLF8SmeaaL25c0QG3IX04HoD0als9gglYg'Payload token:
{ "jti": "zzzz", "iss": "abcd", "aud": "www.example.com", "sub": "test", "iat": 1665660527, "exp": 1865673819 }Dalam kasus ini, kunci
higress_jwt_login_iss#aud#sub##abcd#www.example.com#abcddisimpan dalam instance ApsaraDB for Redis dan nilainya sama dengan yang ada di JWT saat ini.Tolak permintaan akses ketika payload JWT dalam permintaan memiliki karakteristik payload yang sama.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo' # Hasil berikut dikembalikan: {"message":"already login on other device"}Payload token:
{ "jti": "yyyyy", "iss": "abcd", "aud": "www.example.com", "sub": "test", "iat": 1665660527, "exp": 1865673819 }Karakteristik payload sama untuk JWT saat ini dan JWT pada Langkah 1. Namun, bidang non-karakteristik
jtiberbeda antara dua JWT tersebut. Oleh karena itu, permintaan akses berdasarkan JWT ditolak.Lakukan logon paksa.
curl http://xxx.hello.com/test/jwt_login -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo' # Hasil berikut dikembalikan: {"message":"login success"}Dalam kasus ini, kunci
higress_jwt_login_iss#aud#sub##abcd#www.example.com#abcddisimpan dalam instance ApsaraDB for Redis dan nilainya diganti dengan nilai dalam JWT saat ini.Gunakan JWT saat ini untuk berhasil mengakses halaman.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo'Jika Anda menggunakan JWT pada Langkah 1, pesan kegagalan dikembalikan.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6InRlc3QiLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.P0WtBTHJzUJvklu9q8XSRszfPbgojrZHg7t4ZaYfKGo' # Hasil berikut dikembalikan: {"message":"already login on other device"}
Kode kesalahan
Kode status HTTP | Pesan kesalahan | Penyebab |
401 | invalid token | Tidak ada JWT yang disediakan dalam header permintaan, format JWT tidak valid, atau JWT telah kedaluwarsa. |
500 | redis server error | Akses ke instance ApsaraDB for Redis timeout atau gagal. |