Plugin jwt-logout menggunakan Redis untuk mengimplementasikan manajemen status lemah pada Token Web JSON (JWT), memungkinkan invalidasi JWT secara proaktif dan kontrol logon satu perangkat. Misalnya, ketika pengguna masuk dari perangkat baru, sesi sebelumnya akan secara otomatis diinvalidasi.
Jenis plugin
Plugin untuk autentikasi dan otorisasi.
Fields
|
Field |
Data type |
Required |
Default value |
Description |
|
jwks |
string |
No |
- |
String JSON untuk verifikasi JWT. Tidak diperlukan jika plugin ini digunakan bersama plugin jwt-auth. Untuk informasi selengkapnya, lihat JSON Web Key (JWK). |
|
clock_skew |
number |
No |
60 |
Skew jam yang diizinkan saat memverifikasi field exp dan iat dalam JWT. Satuan: detik. |
|
token_header |
string |
No |
Authorization |
Header permintaan tempat JWT diekstraksi. |
|
token_prefix |
string |
No |
"Bearer" |
Awalan nilai header. Setelah awalan dihapus, bagian yang tersisa digunakan sebagai JWT. |
|
redis |
Redis |
Yes |
- |
Konfigurasi layanan Redis. |
|
logout |
Logout |
No |
- |
Konfigurasi untuk fitur logoff JWT. Jika tidak dikonfigurasi, logoff JWT dinonaktifkan. |
|
login |
Login |
No |
- |
Konfigurasi untuk fitur logon satu perangkat JWT. Jika tidak dikonfigurasi, logon satu perangkat dinonaktifkan. |
Tabel berikut menjelaskan field konfigurasi tipe Redis.
|
Field |
Data type |
Required |
Default value |
Description |
|
service |
string |
Yes |
- |
Nama layanan Redis. Contoh:
|
|
port |
number |
Yes |
- |
Nomor port layanan Redis. |
|
username |
string |
No |
- |
Username untuk perintah AUTH Redis. |
|
password |
string |
No |
- |
Password untuk perintah AUTH Redis. |
|
timeout |
number |
No |
1000 |
Periode timeout untuk perintah Redis. Satuan: milidetik. |
Tabel berikut menjelaskan field konfigurasi tipe Logout.
|
Field |
Data type |
Required |
Default value |
Description |
|
key_prefix |
string |
No |
higress_jwt_logout_ |
Awalan kunci yang disimpan di Redis. |
|
key |
array of string |
No |
["jti"] |
Kunci dalam muatan JWT yang mengidentifikasi JWT. Jika kunci yang sama muncul dalam muatan beberapa JWT, JWT tersebut dianggap identik. Jika kunci tidak ada dalam muatan JWT, error token tidak valid 401 dikembalikan. |
|
path |
string |
No |
/jwt_logout |
String yang digunakan untuk mencocokkan akhiran path URL. Jika cocok, JWT dalam permintaan saat ini diinvalidasi dan tidak dapat digunakan lagi. |
|
error_status |
number |
No |
401 |
Kode status HTTP yang dikembalikan ketika JWT yang telah dilogoff digunakan. |
|
error_body |
string |
No |
'{"message":"invalid token"}' |
Isi respons yang dikembalikan ketika JWT yang telah dilogoff digunakan. |
|
ttl |
number |
No |
- |
Time to live (TTL) kunci yang disimpan di Redis. Satuan: detik. Menentukan berapa lama JWT tetap diinvalidasi setelah logoff. Jika tidak ditentukan, TTL sama dengan nilai field exp dalam muatan dikurangi waktu saat ini. Jika muatan tidak berisi field exp, TTL default adalah 86.400 detik (24 jam). |
Tabel berikut menjelaskan field konfigurasi tipe Login.
|
Field |
Data type |
Required |
Default value |
Description |
|
key_prefix |
string |
No |
higress_jwt_logout_ |
Awalan kunci yang disimpan di Redis. |
|
key |
array of string |
No |
["iss","aud","sub"] |
Identifikasi logon satu perangkat dalam muatan JWT. Jika JWT permintaan saat ini berisi nilai field yang sama dengan JWT terautentikasi sebelumnya tetapi bukan JWT yang persis sama, permintaan ditolak sebagai logon duplikat. Akses ditolak hingga kunci Redis untuk JWT terautentikasi tersebut kedaluwarsa. Jika field tidak ada dalam muatan JWT, error token tidak valid 401 dikembalikan. |
|
path |
string |
No |
/jwt_login |
String yang digunakan untuk mencocokkan akhiran path URL. Jika cocok, JWT permintaan saat ini menjadi token sesi aktif, dan JWT terautentikasi sebelumnya dengan karakteristik muatan yang sama diinvalidasi. |
|
error_status |
number |
No |
403 |
Kode status HTTP yang dikembalikan untuk upaya logon duplikat. |
|
error_body |
string |
No |
'{"message":"already login on other device"}' |
Isi respons yang dikembalikan untuk upaya logon duplikat. |
|
ttl |
number |
No |
- |
TTL kunci yang disimpan di Redis. Satuan: detik. Menentukan periode validitas JWT logon satu perangkat. Jika tidak ditentukan, TTL sama dengan nilai field exp dalam muatan dikurangi waktu saat ini. Jika muatan tidak berisi field exp, TTL default adalah 86.400 detik (24 jam). |
Contoh konfigurasi
Menggunakan instans ApsaraDB for Redis
-
Buat instans ApsaraDB for Redis. Untuk informasi selengkapnya, lihat Ikhtisar.
-
Aktifkan konfigurasi logoff dan logon. Saat plugin memproses permintaan, satu permintaan baca Redis dilakukan untuk pemeriksaan konfigurasi logoff dan dua permintaan baca Redis untuk pemeriksaan konfigurasi logon. Dalam kasus langka seperti logoff atau logon pertama kali, dua permintaan tulis Redis tambahan dibuat. Untuk memperkirakan kapasitas instans ApsaraDB for Redis, kalikan throughput permintaan yang diproses oleh plugin dengan 2.
-
Setelah mengonfigurasi instans ApsaraDB for Redis, peroleh titik akhir VPC instans tersebut. Contoh: r-xxxxxxx.redis.rds.aliyuncs.com.
-
Tambahkan layanan. Pilih DNS Domain Name dari daftar drop-down Service Source, masukkan nomor port Redis (umumnya 6379) di bidang Service Port, masukkan titik akhir VPC di bidang Domain Names, dan pilih Disabled dari daftar drop-down TLS Mode. Untuk informasi selengkapnya, lihat Buat layanan.
-
Tambahkan konten berikut ke konfigurasi plugin untuk menghubungkan ke instans ApsaraDB for Redis:
redis: service: redis.dns port: 6379Jika Anda mengonfigurasi password untuk layanan Redis, tambahkan konten berikut:
redis: service: redis.dns port: 6379 password: ****** # Masukkan password yang Anda tentukan.
Mengimplementasikan fitur logoff JWT
Skenario penggunaan
JWT adalah token tanpa status yang tetap valid hingga kedaluwarsa. Gunakan plugin jwt-logout untuk memaksa menginvalidasi JWT tertentu sebelum masa berlakunya habis.
Cara kerja
-
Jika akhiran path permintaan cocok dengan path dalam konfigurasi plugin, mekanisme logoff dipicu. Instans ApsaraDB for Redis mencatat JWT untuk logoff tersebut. Kunci yang disimpan di instans ApsaraDB for Redis terdiri dari awalan yang dikonfigurasi serta kunci dan nilai yang diekstraksi dari muatan JWT saat ini.
-
Jika muatan JWT yang dibawa dalam permintaan sesuai dengan karakteristik kunci yang disimpan di instans ApsaraDB for Redis, sistem menganggap JWT tersebut tidak valid dan menolak permintaan tersebut.
-
Waktu kedaluwarsa default kunci yang disimpan di instans ApsaraDB for Redis dihitung berdasarkan field
expdalam muatan JWT. Artinya, kunci dapat disimpan hingga JWT kedaluwarsa.
-
Kunci logoff default yang direkomendasikan plugin adalah ["jti"], di mana
jtiadalah field muatan yang secara unik mengidentifikasi JWT. Sesuai standar JWT, jika nilaijtidalam muatan JWT sama dengan yang dicatat di instans ApsaraDB for Redis, seluruh JWT tersebut persis sama. Oleh karena itu, jti dapat digunakan untuk menandai status logoff JWT. -
Aturan penggabungan kunci yang disimpan di instans 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. -
Plugin ini hanya dapat menginvalidasi token yang dibawa dalam permintaan saat ini selama logoff. Anda juga dapat secara manual menentukan token di konsol ApsaraDB for Redis berdasarkan aturan penggabungan kunci di atas. Jika gerbang menemukan bahwa kunci tersebut ada di instans ApsaraDB for Redis, gerbang akan menolak permintaan akses yang didasarkan pada JWT terkait.
Contoh
Konfigurasi plugin:
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"}Muatan token:
{ "jti": "xxxx", "iss": "abcd", "sub": "test", "aud": "www.test.com", "iat": 1665660527, "exp": 1865673819 }Dalam kasus ini, kunci
higress_jwt_logout_jti##xxxxdisimpan di instans ApsaraDB for Redis. -
Setelah logoff, akses berdasarkan JWT tersebut tidak diizinkan.
curl http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsInN1YiI6InRlc3QiLCJhdWQiOiJ3d3cudGVzdC5jb20iLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.tmKF6qc1mOWNyCCzBOT2XKNoEGeEgr3EbhTKAQfq1io' # Hasil berikut dikembalikan: {"message":"invalid token"}
Mengimplementasikan logoff paksa berdasarkan JWT
Skenario penggunaan
Saat akun masuk dari beberapa perangkat dengan autentikasi JWT, JWT berbeda mungkin dikeluarkan untuk setiap perangkat. Gunakan plugin jwt-logout untuk memberlakukan logon satu perangkat sehingga hanya satu sesi yang tetap aktif pada satu waktu.
Cara kerja
-
Saat permintaan diajukan, sistem mengekstraksi JWT dari permintaan tersebut dan membentuk kunci Redis berdasarkan awalan yang dikonfigurasi serta kunci dan nilai yang diekstraksi dari muatan JWT saat ini. Sistem kemudian menanyakan nilai yang sesuai dengan kunci tersebut di instans ApsaraDB for Redis. Jika nilainya tidak sesuai dengan nilai kunci JWT saat ini, sistem menolak permintaan akses tersebut.
-
Jika nilai tersebut tidak ada, JWT saat ini ditulis ke kunci Redis. Waktu kedaluwarsa default kunci di instans ApsaraDB for Redis dihitung berdasarkan field
expdalam muatan JWT. Artinya, kunci dapat disimpan hingga JWT kedaluwarsa. Selama periode validitas JWT, permintaan akses berdasarkan JWT lain yang memiliki karakteristik muatan yang sama tidak diizinkan. -
Jika akhiran path permintaan cocok dengan
pathdalam konfigurasi plugin, mekanisme logoff paksa dipicu dan JWT saat ini ditulis ke nilai kunci Redis terkait. JWT yang digunakan untuk logon sukses dan memiliki karakteristik muatan yang sama diinvalidasi saat logoff. Hal ini menjamin logon satu perangkat.
-
Kunci logon default yang direkomendasikan plugin adalah ["iss","aud","sub"]. Dalam kunci tersebut,
issmenunjukkan penerbit JWT,audmenunjukkan skenario penggunaan JWT, dansubmenunjukkan subjek JWT. Dalam kebanyakan kasus, kombinasi ini dapat digunakan untuk menjamin logon satu perangkat. -
Aturan penggabungan kunci yang disimpan di instans 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 yang memiliki karakteristik muatan yang sama, JWT pertama yang digunakan untuk permintaan secara otomatis ditulis ke instans ApsaraDB for Redis. Hal ini membantu mengimplementasikan fitur logon satu perangkat plugin. 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 di instans ApsaraDB for Redis dihapus. Aturan ini juga berlaku saat Anda mengaktifkan fitur logoff JWT.
Contoh
Konfigurasi plugin:
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'Muatan 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 di instans ApsaraDB for Redis dan nilainya sama dengan yang ada dalam JWT saat ini. -
Tolak permintaan akses ketika muatan JWT dalam permintaan memiliki karakteristik muatan 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"}Muatan token:
{ "jti": "yyyyy", "iss": "abcd", "aud": "www.example.com", "sub": "test", "iat": 1665660527, "exp": 1865673819 }Karakteristik muatan sama antara JWT saat ini dan JWT pada Langkah 1. Namun, field non-karakteristik
jtiberbeda antara kedua JWT tersebut. Oleh karena itu, permintaan akses berdasarkan JWT tersebut 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 di instans 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 error
|
Kode status HTTP |
Pesan error |
Alasan |
|
401 |
invalid token |
Tidak ada JWT yang disediakan dalam header permintaan, format JWT tidak valid, atau JWT telah kedaluwarsa atau diinvalidasi. |
|
500 |
redis server error |
Instans ApsaraDB for Redis tidak dapat dijangkau atau koneksi timeout. |