JJWT bertujuan untuk menjadi perpustakaan yang paling mudah digunakan dan dipahami untuk membuat dan memverifikasi JSON Web Tokens (JWTs) dan JSON Web Keys (JWKs) di JVM dan Android.
JJWT adalah implementasi Java murni yang secara eksklusif didasarkan pada spesifikasi RFC Kelompok Kerja JOSE:
RFC 7519: Token Web JSON (JWT)
RFC 7515: Tanda Tangan Web JSON (JWS)
RFC 7516: Enkripsi Web JSON (JWE)
RFC 7517: Kunci Web JSON (JWK)
RFC 7518: Algoritma Web JSON (JWA)
RFC 7638: Sidik Jari Kunci Web JSON
RFC 9278: URI Sidik Jari Kunci Web JSON
RFC 7797: Opsi Muatan JWS Tidak Dikodekan
RFC 8037: Algoritma Edwards Curve dan JWK
Itu dibuat oleh Les Hazlewood dan didukung serta dikelola oleh komunitas kontributor.
JJWT adalah open source di bawah ketentuan Lisensi Apache 2.0.
PublicKey
JWK PribaditoString()
KeamananBerfungsi penuh di semua Java 7+ JDK dan Android
Praktik dan pernyataan keamanan terbaik otomatis
API yang mudah dipelajari dan dibaca
Antarmuka lancar yang nyaman dan mudah dibaca, bagus untuk pelengkapan otomatis IDE untuk menulis kode dengan cepat
Sepenuhnya sesuai dengan spesifikasi RFC pada semua fungsi yang diimplementasikan, diuji terhadap vektor pengujian yang ditentukan RFC
Implementasi yang stabil dengan hampir 1.700 pengujian dan menerapkan cakupan kode pengujian 100%. Setiap metode, pernyataan, dan varian cabang bersyarat di seluruh basis kode diuji dan diwajibkan untuk meneruskan setiap build.
Membuat, menguraikan, dan memverifikasi JWT ringkas yang ditandatangani secara digital (alias JWS) dengan semua algoritme JWS standar:
Pengidentifikasi | Algoritma Tanda Tangan |
---|---|
| HMAC menggunakan SHA-256 |
| HMAC menggunakan SHA-384 |
| HMAC menggunakan SHA-512 |
| ECDSA menggunakan P-256 dan SHA-256 |
| ECDSA menggunakan P-384 dan SHA-384 |
| ECDSA menggunakan P-521 dan SHA-512 |
| RSASSA-PKCS-v1_5 menggunakan SHA-256 |
| RSASSA-PKCS-v1_5 menggunakan SHA-384 |
| RSASSA-PKCS-v1_5 menggunakan SHA-512 |
| RSASSA-PSS menggunakan SHA-256 dan MGF1 dengan SHA-256 1 |
| RSASSA-PSS menggunakan SHA-384 dan MGF1 dengan SHA-384 1 |
| RSASSA-PSS menggunakan SHA-512 dan MGF1 dengan SHA-512 1 |
| Algoritma Tanda Tangan Digital kurva Edwards 2 |
1. Memerlukan Java 11 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
2 . Memerlukan Java 15 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
Membuat, menguraikan, dan mendekripsi JWT kompak terenkripsi (alias JWE) dengan semua algoritma enkripsi JWE standar:
Pengidentifikasi | Algoritma Enkripsi |
---|---|
| Algoritma enkripsi terautentikasi AES_128_CBC_HMAC_SHA_256 |
| Algoritma enkripsi terautentikasi AES_192_CBC_HMAC_SHA_384 |
| Algoritma enkripsi terautentikasi AES_256_CBC_HMAC_SHA_512 |
| AES GCM menggunakan kunci 128-bit 1 |
| AES GCM menggunakan kunci 192-bit 1 |
| AES GCM menggunakan kunci 256-bit 1 |
1 . Memerlukan Java 8 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
Semua Algoritma Manajemen Kunci untuk mendapatkan kunci enkripsi dan dekripsi JWE:
Pengidentifikasi | Algoritma Manajemen Kunci |
---|---|
| RSAES-PKCS1-v1_5 |
| RSAES OAEP menggunakan parameter default |
| RSAES OAEP menggunakan SHA-256 dan MGF1 dengan SHA-256 |
| Bungkus Kunci AES dengan nilai awal default menggunakan kunci 128-bit |
| Bungkus Kunci AES dengan nilai awal default menggunakan kunci 192-bit |
| Bungkus Kunci AES dengan nilai awal default menggunakan kunci 256-bit |
| Penggunaan langsung kunci simetris bersama sebagai CEK |
| Perjanjian kunci Statis Ephemeral Diffie-Hellman Ephemeral Curve menggunakan Concat KDF |
| ECDH-ES menggunakan Concat KDF dan CEK yang dibalut dengan "A128KW" |
| ECDH-ES menggunakan Concat KDF dan CEK yang dibalut dengan "A192KW" |
| ECDH-ES menggunakan Concat KDF dan CEK yang dibalut dengan "A256KW" |
| Pembungkusan kunci dengan AES GCM menggunakan kunci 128-bit 1 |
| Pembungkusan kunci dengan AES GCM menggunakan kunci 192-bit 1 |
| Pembungkusan kunci dengan AES GCM menggunakan kunci 256-bit 1 |
| PBES2 dengan balutan HMAC SHA-256 dan "A128KW" 1 |
| PBES2 dengan balutan HMAC SHA-384 dan "A192KW" 1 |
| PBES2 dengan balutan HMAC SHA-512 dan "A256KW" 1 |
1 . Memerlukan Java 8 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
Membuat, menguraikan, dan memverifikasi JSON Web Keys (JWKs) di semua format kunci JWA standar menggunakan tipe Java Key
asli:
Format Kunci JWK | Jenis Key Java | Tipe JJWT Jwk |
---|---|---|
Kunci Simetris | | |
Kunci Publik Kurva Elips | | |
Kunci Pribadi Kurva Elips | | |
Kunci Publik RSA | | |
Kunci Pribadi RSA | | |
Kunci Pribadi XDH | | |
Kunci Pribadi XDH | | |
Kunci Publik EdDSA | | |
Kunci Pribadi EdDSA | | |
1 . Memerlukan Java 15 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
2 . Memerlukan Java 15 atau Penyedia JCA yang kompatibel (seperti BouncyCastle) di classpath runtime.
Peningkatan kenyamanan di luar spesifikasi seperti
Kompresi muatan untuk JWT besar apa pun, bukan hanya JWE
Pernyataan klaim (membutuhkan nilai spesifik)
Klaim POJO marshaling dan unmarshalling saat menggunakan parser JSON yang kompatibel (misalnya Jackson)
Pembuatan Kunci Aman berdasarkan algoritma JWA yang diinginkan
dan banyak lagi…
Serialisasi dan parsing non-kompak.
Fitur ini mungkin diterapkan pada rilis mendatang. Kontribusi komunitas dipersilakan!
Jika Anda mengalami kesulitan dalam menggunakan JJWT, harap membaca terlebih dahulu dokumentasi di halaman ini sebelum mengajukan pertanyaan. Kami berusaha keras untuk memastikan dokumentasi JJWT kuat, dikategorikan dengan daftar isi, dan terkini untuk setiap rilis.
Jika dokumentasi atau API JavaDoc tidak memadai, dan Anda memiliki pertanyaan kegunaan atau bingung tentang sesuatu, silakan ajukan pertanyaan Anda di sini. Namun:
Harap jangan membuat masalah GitHub untuk mengajukan pertanyaan.
Kami menggunakan Masalah GitHub untuk melacak pekerjaan yang dapat ditindaklanjuti yang memerlukan perubahan pada desain dan/atau basis kode JJWT. Jika Anda memiliki pertanyaan kegunaan, silakan ajukan pertanyaan Anda di sini, dan kami dapat mengubahnya menjadi masalah jika perlu.
Jika Masalah GitHub dibuat yang tidak mewakili pekerjaan yang dapat ditindaklanjuti untuk basis kode JJWT, masalah tersebut akan segera ditutup.
Jika Anda tidak memiliki pertanyaan kegunaan dan yakin Anda memiliki bug atau permintaan fitur yang sah, silakan diskusikan terlebih dahulu di sini. Silakan lakukan pencarian cepat terlebih dahulu untuk melihat apakah diskusi yang terkait dengan Anda sudah ada dan bergabunglah dalam diskusi yang ada tersebut jika diperlukan.
Jika Anda merasa ingin membantu memperbaiki bug atau mengimplementasikan sendiri fitur baru tersebut, silakan baca bagian Berkontribusi selanjutnya sebelum memulai pekerjaan apa pun.
Permintaan Tarik Sederhana yang memperbaiki apa pun selain kode inti JJWT (dokumentasi, JavaDoc, kesalahan ketik, kasus pengujian, dll) selalu dihargai dan memiliki kemungkinan besar untuk digabungkan dengan cepat. Tolong kirimkan mereka!
Namun, jika Anda ingin atau merasa perlu mengubah fungsionalitas atau kode inti JJWT, mohon jangan mengeluarkan permintaan penarikan tanpa memulai diskusi JJWT baru dan mendiskusikan perubahan yang Anda inginkan terlebih dahulu , sebelum Anda mulai mengerjakannya .
Akan sangat disayangkan jika Anda menolak pull request yang sungguh-sungguh dan sangat dihargai jika hal tersebut mungkin tidak sejalan dengan tujuan proyek, ekspektasi desain, atau fungsionalitas yang direncanakan. Sayangnya kami harus menolak PR besar di masa lalu karena tidak sinkron dengan ekspektasi proyek atau desain - semua karena penulis PR tidak menghubungi tim terlebih dahulu sebelum mengerjakan solusi.
Jadi, harap buat diskusi JJWT baru terlebih dahulu untuk didiskusikan, dan kemudian kita dapat dengan mudah mengubah diskusi tersebut menjadi sebuah isu dan kemudian melihat apakah (atau bagaimana) PR diperlukan. Terima kasih!
Jika Anda ingin membantu, namun tidak tahu harus mulai dari mana, silakan kunjungi halaman Masalah yang Dibutuhkan Bantuan dan pilih salah satu yang ada di sana, dan kami akan dengan senang hati berdiskusi dan menjawab pertanyaan di komentar masalah.
Jika salah satu di antaranya tidak menarik bagi Anda, jangan khawatir! Bantuan apa pun yang ingin Anda tawarkan akan dihargai berdasarkan peringatan di atas mengenai kontribusi permintaan penarikan. Jangan ragu untuk berdiskusi atau bertanya terlebih dahulu jika Anda tidak yakin. :)
JSON Web Token (JWT) adalah format pesan berbasis teks tujuan umum untuk mengirimkan informasi dengan cara yang ringkas dan aman. Berlawanan dengan anggapan umum, JWT tidak hanya berguna untuk mengirim dan menerima token identitas di web - meskipun itu adalah kasus penggunaan yang paling umum. JWT dapat digunakan sebagai pesan untuk semua jenis data.
JWT dalam bentuknya yang paling sederhana berisi dua bagian:
Data primer dalam JWT, disebut payload
, dan
Object
JSON dengan pasangan nama/nilai yang mewakili metadata tentang payload
dan pesan itu sendiri, disebut header
.
payload
JWT bisa berupa apa saja - apa pun yang dapat direpresentasikan sebagai array byte, seperti String, gambar, dokumen, dll.
Namun karena header
JWT adalah Object
JSON, masuk akal jika payload
JWT juga bisa menjadi Object
JSON. Dalam banyak kasus, pengembang menyukai payload
berupa JSON yang mewakili data tentang pengguna atau komputer atau konsep identitas serupa. Ketika digunakan dengan cara ini, payload
disebut objek Claims
JSON, dan setiap pasangan nama/nilai dalam objek tersebut disebut claim
- setiap bagian informasi dalam 'mengklaim' sesuatu tentang identitas.
Dan meskipun 'mengklaim' sesuatu tentang suatu identitas bermanfaat, siapa pun sebenarnya bisa melakukannya. Yang penting adalah Anda memercayai klaim tersebut dengan memverifikasi bahwa klaim tersebut berasal dari orang atau komputer yang Anda percayai.
Fitur bagus dari JWT adalah dia dapat diamankan dengan berbagai cara. JWT dapat ditandatangani secara kriptografis (menjadikannya apa yang kami sebut JWS) atau dienkripsi (menjadikannya JWE). Hal ini menambah lapisan kemampuan verifikasi yang kuat pada JWT - penerima JWS atau JWE dapat memiliki tingkat keyakinan yang tinggi bahwa itu berasal dari seseorang yang mereka percayai dengan memverifikasi tanda tangan atau mendekripsinya. Fitur verifikasi inilah yang menjadikan JWT pilihan yang baik untuk mengirim dan menerima informasi yang aman, seperti klaim identitas.
Terakhir, JSON dengan spasi agar mudah dibaca manusia memang bagus, tetapi format pesannya tidak terlalu efisien. Oleh karena itu, JWT dapat dipadatkan (dan bahkan dikompresi) ke representasi minimal - pada dasarnya string yang dikodekan Base64URL - sehingga dapat ditransmisikan di seluruh web dengan lebih efisien, seperti dalam header HTTP atau URL.
Setelah Anda memiliki payload
dan header
, bagaimana keduanya dipadatkan untuk transmisi web, dan seperti apa sebenarnya tampilan JWT akhir? Mari kita lihat versi proses yang disederhanakan dengan beberapa kodesemu:
Asumsikan kita memiliki JWT dengan header
JSON dan muatan pesan teks sederhana:
tajuk
{ "alg": "tidak ada" }
muatan
Tanda sebenarnya dari kecerdasan bukanlah pengetahuan melainkan imajinasi.
Hapus semua spasi yang tidak perlu di JSON:
String header = ' {"alg":"none"} '
String payload = ' The true sign of intelligence is not knowledge but imagination. '
Dapatkan masing-masing byte UTF-8 dan pengkodean Base64URL:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedPayload = base64URLEncode( payload . getBytes( " UTF-8 " ) )
Gabungkan header dan klaim yang dikodekan dengan karakter titik ('.'):
String compact = encodedHeader + ' . ' + encodedPayload + ' . '
String JWT compact
gabungan terakhir terlihat seperti ini:
eyJhbGciOiJub25lIn0.VGhlIHRydWUgc2lnbiBvZiBpbnRlbGxpZ2VuY2UgaXMgbm90IGtub3dsZWRnZSBidXQgaW1hZ2luYXRpb24u.
Ini disebut JWT 'tidak terlindungi' karena tidak ada keamanan yang terlibat - tidak ada tanda tangan digital atau enkripsi untuk 'melindungi' JWT guna memastikan JWT tidak dapat diubah oleh pihak ketiga.
Jika kami ingin menandatangani formulir ringkas secara digital sehingga kami setidaknya dapat menjamin bahwa tidak ada seorang pun yang mengubah data tanpa kami sadari, kami harus melakukan beberapa langkah lagi, yang ditunjukkan berikutnya.
Alih-alih payload teks biasa, contoh berikut mungkin akan menggunakan jenis payload yang paling umum - JSON mengklaim Object
yang berisi informasi tentang identitas tertentu. Kami juga akan menandatangani JWT secara digital untuk memastikan JWT tidak dapat diubah oleh pihak ketiga tanpa sepengetahuan kami.
Asumsikan kita memiliki header
JSON dan payload
klaim :
tajuk
{
"alg" : " HS256 "
}
muatan
{
"sub" : " Joe "
}
Dalam hal ini, header
menunjukkan bahwa algoritma HS256
(HMAC menggunakan SHA-256) akan digunakan untuk menandatangani JWT secara kriptografis. Selain itu, objek payload
JSON memiliki satu klaim, sub
dengan nilai Joe
.
Terdapat sejumlah klaim standar, yang disebut Klaim Terdaftar, dalam spesifikasi dan sub
(untuk 'Subjek') adalah salah satunya.
Hapus semua spasi yang tidak perlu di kedua objek JSON:
String header = ' {"alg":"HS256"} '
String claims = ' {"sub":"Joe"} '
Dapatkan masing-masing byte UTF-8 dan pengkodean Base64URL:
String encodedHeader = base64URLEncode( header . getBytes( " UTF-8 " ) )
String encodedClaims = base64URLEncode( claims . getBytes( " UTF-8 " ) )
Gabungkan header dan klaim yang dikodekan dengan karakter titik '.' pembatas:
String concatenated = encodedHeader + ' . ' + encodedClaims
Gunakan rahasia kriptografi atau kunci pribadi yang cukup kuat, bersama dengan algoritme penandatanganan pilihan Anda (kami akan menggunakan HMAC-SHA-256 di sini), dan tandatangani string gabungan:
SecretKey key = getMySecretKey()
byte [] signature = hmacSha256( concatenated, key )
Karena tanda tangan selalu berupa array byte, enkode Base64URL tanda tangan dan gabungkan ke string concatenated
dengan karakter titik '.' pembatas:
String compact = concatenated + ' . ' + base64URLEncode( signature )
Dan begitulah, String compact
terakhir terlihat seperti ini:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Ini disebut 'JWS' - kependekan dari JWT yang ditandatangani .
Tentu saja, tidak ada seorang pun yang ingin melakukan ini secara manual dalam kode, dan lebih buruk lagi, jika Anda melakukan kesalahan, Anda dapat menimbulkan masalah dan kelemahan keamanan yang serius. Hasilnya, JJWT diciptakan untuk menangani semua ini untuk Anda: JJWT sepenuhnya mengotomatiskan pembuatan JWS serta penguraian dan verifikasi JWS untuk Anda.
Sejauh ini kita telah melihat JWT yang tidak terlindungi dan JWT yang ditandatangani secara kriptografis (disebut 'JWS'). Salah satu hal yang melekat pada keduanya adalah bahwa semua informasi di dalamnya dapat dilihat oleh siapa saja - semua data baik di header maupun payload dapat dilihat oleh publik. JWS hanya memastikan datanya tidak diubah oleh siapa pun - tidak menghalangi siapa pun untuk melihatnya. Sering kali, hal ini tidak masalah karena data di dalamnya bukanlah informasi sensitif.
Namun bagaimana jika Anda perlu merepresentasikan informasi dalam JWT yang dianggap sebagai informasi sensitif - mungkin alamat pos atau nomor jaminan sosial atau nomor rekening bank seseorang?
Dalam kasus ini, kami menginginkan JWT yang sepenuhnya terenkripsi, yang disebut 'JWE'. JWE menggunakan kriptografi untuk memastikan bahwa muatannya tetap terenkripsi dan diautentikasi sepenuhnya sehingga pihak yang tidak berwenang tidak dapat melihat data di dalamnya, atau mengubah data tanpa terdeteksi. Secara khusus, spesifikasi JWE mengharuskan algoritma Enkripsi Otentikasi dengan Data Terkait digunakan untuk mengenkripsi dan melindungi data sepenuhnya.
Ikhtisar lengkap algoritma AEAD berada di luar cakupan dokumentasi ini, namun berikut adalah contoh JWE kompak akhir yang menggunakan algoritma ini (jeda baris hanya untuk dibaca):
eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ
Selanjutnya kita akan membahas cara menginstal JJWT di proyek Anda, dan kemudian kita akan melihat cara menggunakan API lancar JJWT yang bagus alih-alih manipulasi string yang berisiko untuk membangun JWT, JWS, dan JWE dengan cepat dan aman.
Gunakan alat pembangunan favorit Anda yang kompatibel dengan Maven untuk menarik dependensi dari Maven Central.
Ketergantungannya mungkin sedikit berbeda jika Anda bekerja dengan proyek JDK atau proyek Android.
Jika Anda membuat proyek JDK (non-Android), Anda perlu menentukan dependensi berikut:
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-api</ artifactId >
< version >0.12.6</ version >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-impl</ artifactId >
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
< dependency >
< groupId >io.jsonwebtoken</ groupId >
< artifactId >jjwt-jackson</ artifactId > <!-- or jjwt-gson if Gson is preferred -->
< version >0.12.6</ version >
< scope >runtime</ scope >
</ dependency >
<!-- Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId> or bcprov-jdk15to18 on JDK 7
<version>1.76</version>
<scope>runtime</scope>
</dependency>
-->
dependencies {
implementation ' io.jsonwebtoken:jjwt-api:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-impl:0.12.6 '
runtimeOnly ' io.jsonwebtoken:jjwt-jackson:0.12.6 ' // or 'io.jsonwebtoken:jjwt-gson:0.12.6' for gson
/*
Uncomment this next dependency if you are using:
- JDK 10 or earlier, and you want to use RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- JDK 10 or earlier, and you want to use EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- JDK 14 or earlier, and you want to use EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
It is unnecessary for these algorithms on JDK 15 or later.
*/
// runtimeOnly 'org.bouncycastle:bcprov-jdk18on:1.76' // or bcprov-jdk15to18 on JDK 7
}
Proyek Android ingin menentukan dependensi dan pengecualian Proguard berikut, serta Provider
BouncyCastle opsional :
Tambahkan dependensi ke proyek Anda:
dependencies {
api( ' io.jsonwebtoken:jjwt-api:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-impl:0.12.6 ' )
runtimeOnly( ' io.jsonwebtoken:jjwt-orgjson:0.12.6 ' ) {
exclude( group : ' org.json ' , module : ' json ' ) // provided by Android natively
}
/*
Uncomment this next dependency if you want to use:
- RSASSA-PSS (PS256, PS384, PS512) signature algorithms.
- EdECDH (X25519 or X448) Elliptic Curve Diffie-Hellman encryption.
- EdDSA (Ed25519 or Ed448) Elliptic Curve signature algorithms.
** AND ALSO ensure you enable the BouncyCastle provider as shown below **
*/
// implementation('org.bouncycastle:bcprov-jdk18on:1.76') // or bcprov-jdk15to18 for JDK 7
}
Anda dapat menggunakan aturan pengecualian Android Proguard berikut:
-keepattributes Kelas Dalam -pertahankan kelas io.jsonwebtoken.** { *; } -simpan nama kelas io.jsonwebtoken.* { *; } -keepnames antarmuka io.jsonwebtoken.* { *; } -menjaga kelas org.bouncycastle.** { *; } -keepnames class org.bouncycastle.** { *; } -jangan peringatkan org.bouncycastle.**
Jika Anda ingin menggunakan algoritma JWT RSASSA-PSS (yaitu PS256
, PS384
, dan PS512
), EdECDH ( X25512
atau X448
) enkripsi Elliptic Curve Diffie-Hellman, algoritma tanda tangan EdDSA ( Ed25519
atau Ed448
), atau Anda hanya ingin memastikan Android Anda aplikasi menjalankan versi terbaru BouncyCastle, Anda perlu:
Batalkan komentar pada ketergantungan BouncyCastle seperti yang dikomentari di atas di bagian dependensi.
Ganti penyedia BC
kustom Android lama dengan yang diperbarui.
Pendaftaran penyedia perlu dilakukan di awal siklus hidup aplikasi, sebaiknya di kelas Activity
utama aplikasi Anda sebagai blok inisialisasi statis. Misalnya:
class MainActivity : AppCompatActivity () {
companion object {
init {
Security .removeProvider( " BC " ) // remove old/legacy Android-provided BC provider
Security .addProvider( BouncyCastleProvider ()) // add 'real'/correct BC provider
}
}
// ... etc ...
}
Perhatikan semua deklarasi ketergantungan JJWT di atas hanya memiliki satu ketergantungan waktu kompilasi dan sisanya dinyatakan sebagai ketergantungan waktu proses .
Hal ini karena JJWT dirancang sehingga Anda hanya bergantung pada API yang dirancang secara eksplisit untuk Anda gunakan dalam aplikasi Anda dan semua detail implementasi internal lainnya - yang dapat berubah tanpa peringatan - diturunkan ke dependensi waktu proses saja. Ini adalah poin yang sangat penting jika Anda ingin memastikan penggunaan JJWT yang stabil dan peningkatan dari waktu ke waktu:
JJWT menjamin kompatibilitas versi semantik untuk semua artefaknya kecuali |
Hal ini dilakukan untuk memberi manfaat bagi Anda: kehati-hatian dilakukan dalam melakukan kurasi jjwt-api
.jar dan memastikannya berisi apa yang Anda perlukan dan sebisa mungkin tetap kompatibel sehingga Anda dapat mengandalkannya dengan aman dengan cakupan kompilasi. Strategi runtime jjwt-impl
.jar memberi pengembang JJWT fleksibilitas untuk mengubah paket internal dan implementasi kapan pun dan bagaimanapun diperlukan. Hal ini membantu kami menerapkan fitur, memperbaiki bug, dan mengirimkan rilis baru kepada Anda dengan lebih cepat dan efisien.
Sebagian besar kerumitan tersembunyi di balik antarmuka lancar berbasis pembuat yang nyaman dan mudah dibaca, sangat cocok untuk mengandalkan pelengkapan otomatis IDE untuk menulis kode dengan cepat. Berikut ini contohnya:
import io . jsonwebtoken . Jwts ;
import io . jsonwebtoken . security . Keys ;
import java . security . Key ;
// We need a signing key, so we'll create one just for this example. Usually
// the key would be read from your application configuration instead.
SecretKey key = Jwts . SIG . HS256 . key (). build ();
String jws = Jwts . builder (). subject ( "Joe" ). signWith ( key ). compact ();
Seberapa mudahnya itu!?
Dalam hal ini, kami adalah:
membangun JWT yang sub
klaim terdaftarnya (Subjek) akan disetel ke Joe
. Kami kemudian
menandatangani JWT menggunakan kunci yang sesuai untuk algoritma HMAC-SHA-256. Akhirnya, kita
memadatkannya menjadi bentuk String
terakhirnya. JWT yang ditandatangani disebut 'JWS'.
String jws
yang dihasilkan terlihat seperti ini:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4
Sekarang mari kita verifikasi JWT (Anda harus selalu membuang JWT yang tidak cocok dengan tanda tangan yang diharapkan):
assert Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( jws ). getPayload (). getSubject (). equals ( "Joe" );
Ada dua hal yang terjadi di sini. key
dari sebelumnya digunakan untuk memverifikasi tanda tangan JWT. Jika gagal memverifikasi JWT, SignatureException
(yang memperluas JwtException
) akan dilempar. Dengan asumsi JWT diverifikasi, kami menguraikan klaim dan menyatakan bahwa subjek disetel ke Joe
. Anda harus menyukai kode satu baris yang menarik!
CATATAN | JWT yang aman untuk tipe: Untuk mendapatkan hasil JWT |
Namun bagaimana jika parsing atau validasi tanda tangan gagal? Anda dapat menangkap JwtException
dan bereaksi sesuai dengan itu:
try {
Jwts . parser (). verifyWith ( key ). build (). parseSignedClaims ( compactJws );
//OK, we can trust this JWT
} catch ( JwtException e ) {
//don't trust the JWT!
}
Sekarang kita sudah memiliki 'rasa' cepat tentang cara membuat dan mengurai JWT, mari kita bahas API JJWT secara mendalam.
Anda membuat JWT sebagai berikut:
Gunakan metode Jwts.builder()
untuk membuat instance JwtBuilder
.
Secara opsional, tetapkan parameter header
apa pun sesuai keinginan.
Panggil metode pembuat untuk mengatur konten atau klaim payload.
Secara opsional, panggil metode signWith
atau encryptWith
jika Anda ingin menandatangani atau mengenkripsi JWT secara digital.
Panggil metode compact()
untuk menghasilkan string JWT kompak yang dihasilkan.
Misalnya:
String jwt = Jwts . builder () // (1)
. header () // (2) optional
. keyId ( "aKeyId" )
. and ()
. subject ( "Bob" ) // (3) JSON Claims, or
//.content(aByteArray, "text/plain") // any byte[] content, with media type
. signWith ( signingKey ) // (4) if signing, or
//.encryptWith(key, keyAlg, encryptionAlg) // if encrypting
. compact (); // (5)
payload
JWT dapat berupa byte[]
content (melalui content
) atau JSON Claims (seperti subject
, claims
, dll), namun tidak keduanya.
Tanda tangan digital ( signWith
) atau enkripsi ( encryptWith
) dapat digunakan, namun tidak keduanya.
JWT yang tidak dilindungi : Jika Anda tidak menggunakan metode pembuat |
Header JWT adalah Object
JSON yang menyediakan metadata tentang konten, format, dan operasi kriptografi apa pun yang relevan dengan payload
JWT. JJWT menyediakan sejumlah cara untuk mengatur keseluruhan header dan/atau beberapa parameter header individual (pasangan nama/nilai).
Cara termudah dan direkomendasikan untuk menyetel satu atau lebih parameter header JWT (pasangan nama/nilai) adalah dengan menggunakan pembuat header()
JwtBuilder
sesuai keinginan, lalu memanggil metode and()
untuk kembali ke JwtBuilder
untuk konfigurasi lebih lanjut . Misalnya:
String jwt = Jwts . builder ()
. header () // <----
. keyId ( "aKeyId" )
. x509Url ( aUri )
. add ( "someName" , anyValue )
. add ( mapValues )