全部产品
Search
文档中心

API Gateway:Otentikasi dan otorisasi konsumen

更新时间:Nov 10, 2025

API Gateway berbasis cloud mendukung autentikasi global, autentikasi tingkat entri rute, dan otorisasi konsumen untuk memastikan hanya permintaan yang sah yang dapat mengakses layanan. Topik ini menjelaskan cara menggunakan autentikasi dan otorisasi di API Gateway berbasis cloud agar konsumen dapat mengakses sumber daya secara aman.

Informasi latar belakang

Autentikasi dan otorisasi global ideal untuk skenario business-to-consumer (B2C), seperti logon terpadu. Sebaliknya, autentikasi konsumen tingkat entri rute dan tingkat API dirancang untuk skenario business-to-business (B2B), seperti memberikan akses API kepada mitra.

Perbandingan

Otentikasi dan Otorisasi Global

Autentikasi entri rute + Otorisasi konsumen

Skenario

Skema berorientasi pelanggan (ToC), seperti logon dan autentikasi terpadu.

Skema B2B, seperti memberikan akses API kepada mitra.

Perbedaan Inti

Saat Anda mengaktifkan autentikasi, otorisasi juga diaktifkan.

Setelah Anda mengaktifkan autentikasi, Anda harus mengonfigurasi otorisasi secara terpisah.

Titik masuk konfigurasi

Instance > Security Management > Global Authentication and Authorization.

  1. API Management > HTTP API Details > Route Management > Policy Configuration > Consumer Authentication.

  2. API Management > WebSocket API Details > Route Management > Policy Configuration > Consumer Authentication.

  3. API Management > REST API Details > Attach Policy > Consumer Authentication.

  4. Consumer > Consumer Details > Consumer Authorization.

Konfigurasi metode autentikasi (menggunakan autentikasi JWT sebagai contoh)

  1. Masukkan konfigurasi global JWKS saat membuat konfigurasi.

  2. Masukkan nilai untuk bidang issue dan sub. Bidang-bidang ini digunakan untuk memvalidasi Token Web JSON (JWT).

  1. Saat membuat konfigurasi konsumen, masukkan konfigurasi JWKS untuk konsumen tersebut.

  2. Masukkan ID konsumen untuk memverifikasi konsumen yang terkait dengan JWT. Secara default, gerbang menggunakan bidang uid dalam payload sebagai ID konsumen, tetapi Anda dapat menyesuaikan bidang ini.

Konfigurasi metode otorisasi

Saat membuat konfigurasi, masukkan daftar Domain Names dan Paths untuk daftar hitam atau daftar putih.

  • Blacklist Mode: Permintaan untuk Domain Names dan Paths dalam daftar memerlukan autentikasi. Semua permintaan lainnya dapat diakses tanpa autentikasi.

  • Whitelist Mode: Permintaan untuk nama domain dan Paths dalam daftar tidak memerlukan autentikasi. Semua permintaan lainnya memerlukan autentikasi.

  1. Dalam Policy Configuration untuk entri rute atau API, aktifkan Authentication.

  2. Dalam Consumer Authorization, berikan izin ke entri rute atau API yang telah diaktifkan autentikasinya.

Catatan

Setelah Anda mengaktifkan autentikasi konsumen, kebijakan langsung berlaku. Jika entri rute atau API sudah dipublikasikan tetapi belum memiliki konsumen atau aturan otorisasi yang dikonfigurasi, semua permintaan akses akan ditolak secara default.

Menggunakan autentikasi dan otorisasi konsumen

Otentikasi JWT

Tinjauan alur autentikasi JWT

  1. Klien mengirim permintaan autentikasi ke API Gateway. Permintaan biasanya berisi nama pengguna dan kata sandi pengguna akhir.

  2. Gerbang meneruskan permintaan langsung ke layanan backend.

  3. Layanan backend membaca dan memvalidasi informasi verifikasi, seperti nama pengguna dan kata sandi, dari permintaan tersebut. Setelah informasi divalidasi, layanan menggunakan kunci privat untuk menghasilkan token standar dan mengembalikannya ke gerbang.

  4. Gerbang mengembalikan respons yang berisi token ke klien. Klien harus menyimpan cache token ini secara lokal.

  5. Klien mengirim permintaan bisnis ke API Gateway dengan token tersebut.

  6. Gerbang menggunakan kunci publik yang dikonfigurasi pengguna untuk memverifikasi token dalam permintaan. Setelah verifikasi berhasil, permintaan diteruskan ke layanan backend.

  7. Layanan backend memproses logika bisnis dan mengirim respons.

  8. Gerbang mengembalikan respons bisnis ke klien.

Bagian berikut menjelaskan cara menghasilkan token, cara klien mengirim permintaan ke gerbang, dan cara gerbang menggunakan kunci publik yang dikonfigurasi untuk memverifikasi token.

Menghasilkan token dengan layanan autentikasi

Contoh Java berikut menunjukkan cara menghasilkan token. Untuk bahasa lain, gunakan alat yang sesuai untuk menghasilkan pasangan kunci.

  1. Buat proyek Maven dan tambahkan dependensi berikut:

    Pertama, buat proyek Maven dan tambahkan dependensi berikut:

    <dependency>
        <groupId>org.bitbucket.b_c</groupId>
        <artifactId>jose4j</artifactId>
        <version>0.7.0</version>
    </dependency>
  2. Pilih metode untuk menghasilkan token.

    Anda dapat menghasilkan token menggunakan kunci simetris atau kunci asimetris. Pilih metode yang sesuai dengan kebutuhan Anda.

    Menghasilkan token menggunakan kunci simetris

    Contoh kode:

    package org.example;
    
    import java.io.UnsupportedEncodingException;
    import java.security.PrivateKey;
    
    import org.jose4j.base64url.Base64;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.OctJwkGenerator;
    import org.jose4j.jwk.OctetSequenceJsonWebKey;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.keys.HmacKey;
    import org.jose4j.lang.JoseException;
    import sun.lwawt.macosx.CSystemTray;
    
    public class Main {
        public static void main(String[] args) throws JoseException, UnsupportedEncodingException {
            // Gunakan contoh dari topik ini
            String privateKeyJson = "{\n"
                    + "    \"k\": \"VoBG-oyqVoyCr9G56ozmq8n_rlDDyYMQOd_DO4GOkEY\",\n"
                    + "    \"kty\": \"oct\",\n"
                    + "    \"alg\": \"HS256\",\n"
                    + "}";
            JwtClaims claims = new JwtClaims();
            claims.setGeneratedJwtId();
            claims.setIssuedAtToNow();
            // Atur waktu kedaluwarsa kurang dari 7 hari
            NumericDate date = NumericDate.now();
            date.addSeconds(120*60);
            claims.setExpirationTime(date);
            claims.setNotBeforeMinutesInThePast(1);
            // Tambahkan parameter kustom. Semua nilai harus bertipe String.
            // Atur ID konsumen
            claims.setClaim("uid", "11215ac069234abcb8944232b79ae711");
            JsonWebSignature jws = new JsonWebSignature();
            // Atur algoritma enkripsi
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
            jws.setKey(new HmacKey(Base64.decode(JsonUtil.parseJson(privateKeyJson).get("k").toString())));
            jws.setPayload(claims.toJson());
            String jwtResult = jws.getCompactSerialization();
            System.out.println("Hasil Token Web JSON yang dihasilkan adalah: \n" + jwtResult);
        }
    }

    Pengaturan kode:

    • privateKeyJson: Ini adalah JSON Web Key Set (JWKS) yang digunakan saat Anda membuat konsumen. Anda dapat mencatat JWKS saat membuat konsumen atau mengambilnya nanti dari halaman konfigurasi dasar konsumen.

    • Atur ID konsumen. Misalnya, claims.setClaim("uid", "11215ac069234abcb8944232b79ae711"). Konsol menghasilkan ID konsumen default saat Anda membuat konsumen. Anda dapat mengubah ID ini sesuai kebutuhan. Anda juga dapat mengambil ID konsumen dari halaman konfigurasi dasar konsumen.

    • Atur algoritma enkripsi. Misalnya, jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256). Algoritma ini harus sesuai dengan yang ada di JWKS.

      Catatan

      Algoritma enkripsi yang didukung adalah ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512, HS256, HS384, HS512, dan EdDSA.

      Saat menggunakan enkripsi simetris, dekode nilai "k".

      jws.setKey(new HmacKey(Base64.decode(JsonUtil.parseJson(privateKeyJson).get("k").toString())));
    • Atur waktu kedaluwarsa. Waktu kedaluwarsa harus kurang dari 7 hari. Setelah token kedaluwarsa, Anda harus menghasilkannya kembali untuk memastikan keamanan.

      ...
          NumericDate date = NumericDate.now();
          date.addSeconds(120*60);
          claims.setExpirationTime(date);
          claims.setNotBeforeMinutesInThePast(1);
      ...
    • Anda dapat menambahkan parameter kustom ke PAYLOAD JWKS untuk memenuhi kebutuhan bisnis Anda.

    Menghasilkan token menggunakan kunci asimetris

    Contoh kode:

    package org.example;
    
    import java.security.PrivateKey;
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.lang.JoseException;
    import org.jose4j.jwk.RsaJsonWebKey;
    
    public class Main {
        public static void main(String[] args) throws JoseException {
            // Contoh kunci dalam format JWK
            String privateKeyJson = "{"
                    + "\"kty\":\"RSA\","
                    + "\"n\":\"u-8lR9lyRhu8tl4vRxOl7yfshssx5jRstabc9n4Rxrz102Z7TPFYrXBZHgf67Y0d-zx9tWd5j91WZxLHv4K6VWPN7zEWEQNn3vUg76dPHPzVkZJWziFPS1EvS4a2gRZdrE4nPogaQ72WySVC0yUF2fL0NKeOclD__coCFxn4QQjcDXyu_CUbI_FuDcdw267mVjjylAaFvOZHH0pXsV8m5zXlpc2aiemWYQJD9MtWRcoKlexWMkTwbEqW5-NWAl0Uo202ahDA1NiaQ98Ch4nw6g2E1GvwxxHkbvMuZcs5z8F5Ct_w0IPtvY7ngSyEN-WCU40oj-C5NUCy_73FpXXdWQ\","
                    + "\"e\":\"AQAB\","
                    + "\"d\":\"Uxg1IqSZazg-Y2AXhVTBrJG5egwD3yZU3qiN0IsDbx0DkFoisG2R6PXg4W9j2n7nv7sKVhgPXrXdyys5mIrDuperaVQJzrHzzlgSHQSb7VQ5Vekfanq95a5avAkvTrpF5raTkYl6G3OLZRqNhnA7Oxe6NEHVsOPxnBQignZgFtiBtCSZY4RVH6Dx4jFfBBNMC9ifyLWLpHut7eczvxI412nBkxgtEjSeFe083NlumO_ZYHbijPcQf5zFWPLEj2EvlgbSwhjc-uSAF4OljAyG_DHZYvztEIGMdxMgBHgwtEvCfzS6PeUgvUR-SB7m_L8z4gjz6TlpSYe3CnZqE69KdQ\","
                    + "\"p\":\"9mNw8U_GxbcSknueUeFFSU9wKD9E9P2ZO5RP5d7o3qGUXOfbrH_g5GMH3YJiPBDZs_2BYFrAACOY4YM-QTiXWVs4xS3OeD8AdH3wEXR_3DMEkOez3cNq3Jy3ZJabm7IUnPMIWv5gpIHghcx0YTtM5RabSgexLMKh2-6sB466378\","
                    + "\"q\":\"w0PzXI_8Q5jv15OUq-dV_Z0kp91Icumf6PEERZN4v3i3VolLBnamMiIQiF74ywclKpZmtfOQTfyL41Xj2vbm2Aus6akRsU3NhQlVtIQTzHWUuEQgMIJYDK7--FzEcZORm1qBiEffiWv6U-slyCcLcNDNT-wjMX8BrS4oWHIoCOc\","
                    + "\"dp\":\"fRRiY76yE_EqVn63Eq4ftGXFdEkaQpzzS1GxderBoTO506hI1rtcedTkS0lDgWa0fjE1mqq3SdrIY8NyuT13Z_9tRHxKkrS5EGpWkyXnOuwTZ1SY9P2dpD1SxJfIizPOTxb5qOf2O81LI-F1O18VXD8rultJUIXGEZaKcpO8vpU\","
                    + "\"dq\":\"V6EP_vMzD5b707AMYVURFx7Fi3vX_pHvzJcVBrBW2P6wsGouvDjU_tygtMKCPoL3X_RdJbynfwgeMyihd-ujz0L2F2pjYUF8QP7ecoNvays9UbBpDbwBDbge_pCLLDlAeAqW5PT0UXSew7hcnUVAciGSchKT_Kt1siVrv72DT_M\","
                    + "\"qi\":\"w5fENzxOivbbbUbawAWSuLgWPtvbTKn2XuPzwr_JzZH08-nadWwQFChcvAiCs8V-306TQOh8NfY308QpGDIq-iRfrS7CEePOjRzpHJfsaQ1IFQqzgDZ9VGdJRDlZqRHx0DbqwMlleVKTC6ER6varalbr4lKU-ZPUQLCzj0e4PMs\""
                    + "}";
    
            JwtClaims claims = new JwtClaims();
            claims.setGeneratedJwtId(); // Menghasilkan jti (JWT ID) secara otomatis
            claims.setIssuedAtToNow();  // Mengatur waktu penerbitan (iat) ke waktu saat ini
    
            // Atur waktu kedaluwarsa kurang dari 7 hari
            NumericDate date = NumericDate.now();
            date.addSeconds(120 * 60); // Atur waktu kedaluwarsa menjadi waktu saat ini ditambah 120 menit
            claims.setExpirationTime(date);
            claims.setNotBeforeMinutesInThePast(1); // Atur waktu not-before (nbf) menjadi 1 menit sebelumnya
    
            // Tambahkan parameter kustom. Semua nilai harus bertipe String.
            // Atur ID konsumen
            claims.setClaim("uid", "11215ac069234abcb8944232b79ae711");
    
            JsonWebSignature jws = new JsonWebSignature();
            // Atur algoritma enkripsi menjadi RSA-SHA256
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    
            // Urai kunci privat dan atur dalam penandatangan
            PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();
            jws.setKey(privateKey);
    
            // Atur konten payload
            jws.setPayload(claims.toJson());
    
            // Hasilkan JWT
            String jwtResult = jws.getCompactSerialization();
            System.out.println("Hasil Token Web JSON yang dihasilkan adalah: \n" + jwtResult);
        }
    }
    

    Pengaturan kode:

    • Atur privateKeyJson, ID konsumen, dan waktu kedaluwarsa. Ini sama seperti pada algoritma enkripsi simetris.

      Atur algoritma enkripsi. Misalnya, jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256). Algoritma ini harus sesuai dengan yang ada di JWKS.

      Untuk mengenkripsi data menggunakan algoritma enkripsi kunci asimetris, Anda harus menggunakan kunci privat.

      ...
          jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
          PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();
          jws.setKey(privateKey);
      ...
    • Anda dapat menambahkan parameter kustom ke PAYLOAD JWT sesuai kebutuhan.

Mengirim permintaan bisnis dari klien ke gerbang

API Gateway berbasis cloud mendukung melewatkan token dalam header. Anda dapat menyesuaikan nama header permintaan dan awalan token. Selama validasi permintaan, kunci dan awalan harus sesuai dengan konfigurasi autentikasi konsumen.

  • Jika permintaan tidak berisi JWT, kesalahan 401 dikembalikan.

    curl  http://xxx.hello.com/test
  • Jika permintaan berisi JWT yang tidak valid, kesalahan 401 dikembalikan.

    curl  http://xxx.hello.com/test -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ1'
  • Jika permintaan berisi JWT yang valid tetapi konsumen tidak memiliki izin untuk mengakses API atau entri rute, kesalahan 403 dikembalikan.

    # consumer1 tidak diotorisasi untuk entri rute atau API pada path berikut
    
    curl  'http://xxx.example.com/test' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

Memverifikasi token di sisi server

Verifikasi token di sisi server melibatkan tiga langkah berikut:

  1. Saat server menerima permintaan pengguna, pertama-tama memeriksa apakah token disertakan. Jika tidak, permintaan ditolak dengan kesalahan 401.

  2. Untuk permintaan yang berisi token, server menggunakan kunci publik dari JWKS yang dikonfigurasi untuk memverifikasi bahwa token valid dan belum kedaluwarsa. Jika token tidak valid atau kedaluwarsa, permintaan ditolak dengan kesalahan 401.

  3. Jika token valid, server kemudian memeriksa apakah konsumen yang diwakili oleh token tersebut diotorisasi untuk mengakses API atau entri rute yang diminta.

Kode kesalahan umum

Kode status HTTP

Pesan kesalahan

Penyebab

401

Jwt missing

Header permintaan tidak berisi JWT.

401

Jwt expired

JWT telah kedaluwarsa.

401

Jwt verification fails

Verifikasi payload JWT gagal. Misalnya, klaim `iss` tidak cocok.

403

Access Denied

Tidak memiliki izin untuk mengakses entri rute saat ini.

Otentikasi AK/SK (HMAC)

Menghasilkan tanda tangan di sisi klien

Alur pembuatan tanda tangan di sisi klien:

  1. Ekstrak string yang akan ditandatangani: Ekstrak data kunci dari permintaan asli untuk membuat string yang akan ditandatangani.

  2. Hasilkan tanda tangan: Gunakan algoritma enkripsi dan Secret Key (SK) yang dikonfigurasi untuk mengenkripsi string yang akan ditandatangani dan menghasilkan tanda tangan.

  3. Tambahkan tanda tangan: Tambahkan semua header terkait tanda tangan ke permintaan HTTP asli untuk membuat permintaan HTTP akhir.

Langkah 1: Ekstrak string yang akan ditandatangani

Klien perlu mengekstrak data kunci dari permintaan HTTP dan menggabungkannya menjadi string yang akan ditandatangani. Format string yang akan ditandatangani yang dihasilkan adalah sebagai berikut:

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

Ketujuh bidang ini membentuk seluruh string yang akan ditandatangani. Bidang-bidang dipisahkan oleh line feed (`\n`). Jika bidang `Headers` kosong, jangan tambahkan line feed setelah bidang `Headers`. Untuk semua bidang kosong lainnya, Anda harus tetap mempertahankan line feed. Tanda tangan bersifat case-sensitive. Aturan untuk mengekstrak setiap bidang adalah sebagai berikut:

  • HTTPMethod: Metode HTTP dalam huruf besar. Misalnya, POST.

  • Accept: Nilai header `Accept` dalam permintaan. Bidang ini bisa kosong. Anda harus secara eksplisit mengatur header `Accept`. Jika header ini kosong, beberapa klien HTTP menetapkan nilai default */*, yang menyebabkan verifikasi tanda tangan gagal.

  • Content-MD5: Nilai header `Content-MD5` dalam permintaan. Bidang ini bisa kosong. Anda harus menghitung header `Content-MD5` hanya jika permintaan memiliki badan yang bukan dalam format form. Kode Java berikut menunjukkan cara menghitung nilai Content-MD5:

    String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
  • Content-Type: Nilai header `Content-Type` dalam permintaan. Bidang ini bisa kosong.

  • Date: Nilai header `Date` dalam permintaan. Bidang ini bisa kosong jika konfigurasi date_offset tidak diaktifkan. Jika diaktifkan, gerbang menggunakan bidang ini untuk verifikasi offset waktu.

  • Headers: Anda dapat memilih header tertentu untuk dimasukkan dalam tanda tangan. Aturan untuk menggabungkan string header adalah sebagai berikut:

    • Kunci header yang dimasukkan dalam perhitungan tanda tangan diurutkan secara alfabetis lalu digabungkan sebagai berikut.

      HeaderKey1 + ":" + HeaderValue1 + "\n"\+
      HeaderKey2 + ":" + HeaderValue2 + "\n"\+
      ...
      HeaderKeyN + ":" + HeaderValueN + "\n"
    • Jika nilai header kosong, gunakan `HeaderKey+":"+"\n"` untuk tanda tangan. Kunci dan titik dua harus dipertahankan.

    • Daftar kunci header yang dimasukkan dalam tanda tangan, dipisahkan koma, ditempatkan dalam header `X-Ca-Signature-Headers`.

    • Header berikut tidak dimasukkan dalam perhitungan tanda tangan header: `X-Ca-Signature`, `X-Ca-Signature-Headers`, `Accept`, `Content-MD5`, `Content-Type`, dan `Date`.

  • PathAndParameters: Bidang ini berisi path dan semua parameter dari query dan form. Strukturnya sebagai berikut:

    Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
    Penting
    • Kunci pasangan parameter query dan form diurutkan secara alfabetis lalu digabungkan seperti yang ditunjukkan di atas.

    • Jika tidak ada parameter query atau form, gunakan hanya path. Jangan tambahkan ?.

    • Jika nilai parameter kosong, hanya sertakan kuncinya dalam tanda tangan. Jangan tambahkan tanda sama dengan.

    • Jika ada parameter array dalam query atau form (kunci sama, nilai berbeda), gunakan nilai pertama untuk perhitungan tanda tangan.

Langkah 2: Enkripsi tanda tangan

Setelah klien mengekstrak data kunci dari permintaan HTTP dan merakit string yang akan ditandatangani, klien harus mengenkripsi string tersebut dan mengkodekan hasilnya untuk menghasilkan tanda tangan akhir. Format enkripsi adalah sebagai berikut, di mana stringToSign adalah string yang akan ditandatangani yang diekstrak, secret adalah Secret Key (SK) dari konfigurasi autentikasi Access Key (AK)/SK, dan sign adalah tanda tangan yang dihasilkan:

Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.encodeBase64String(result);

Ringkasnya: Kodekan stringToSign menggunakan UTF-8 untuk mendapatkan array byte. Enkripsi array byte dengan algoritma yang ditentukan. Kemudian, kodekan hasilnya menggunakan Base64 untuk menghasilkan tanda tangan akhir.

Langkah 3: Tambahkan tanda tangan

Klien harus menyertakan empat header berikut dalam permintaan HTTP yang dikirim ke API Gateway untuk verifikasi tanda tangan:

  • x-ca-key: Nilainya adalah Access Key (AK) dari konfigurasi autentikasi AK/SK.

  • x-ca-signature-method: Algoritma tanda tangan. Nilai yang valid adalah `HmacSHA256` atau `HmacSHA1`. Ini opsional. Nilai default adalah `HmacSHA256`.

  • x-ca-signature-headers: Daftar kunci header yang ditandatangani, dipisahkan koma. Ini opsional.

  • x-ca-signature: Tanda tangan. Ini wajib.

Memverifikasi tanda tangan di sisi server

Tinjauan verifikasi tanda tangan klien di sisi server:

  1. Ekstrak string yang akan ditandatangani: Ekstrak data kunci dari permintaan yang diterima untuk membuat string yang akan ditandatangani.

  2. Ekstrak AK: Baca AK dari permintaan yang diterima dan gunakan untuk menemukan SK yang sesuai.

  3. Hitung tanda tangan: Gunakan algoritma enkripsi dan SK untuk mengenkripsi string yang akan ditandatangani dan menghasilkan tanda tangan.

  4. Verifikasi tanda tangan: Baca tanda tangan klien dari permintaan yang diterima dan bandingkan dengan tanda tangan yang dihasilkan server untuk memastikan konsistensi.

Penanganan kesalahan

Jika gerbang gagal memverifikasi tanda tangan, gerbang mengembalikan string yang akan ditandatangani dari sisi server ke klien dalam header X-Ca-Error-Message pada respons HTTP. Anda dapat mengidentifikasi masalah dengan membandingkan string yang akan ditandatangani dari sisi klien dengan string yang akan ditandatangani dari sisi server. Jika nilai string yang akan ditandatangani dari klien dan server sama, periksa SK yang digunakan untuk perhitungan tanda tangan. Karena header HTTP tidak dapat berisi line feed, line feed dalam string yang akan ditandatangani diganti dengan #, seperti yang ditunjukkan di bawah ini:

X-Ca-Error-Message:  Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`

Kode kesalahan terkait

Kode status HTTP

Pesan kesalahan

Penyebab

401

Invalid Key

Header `x-ca-key` tidak disediakan atau tidak valid.

401

Empty Signature

Header `x-ca-signature` tidak disediakan.

400

Invalid Signature

Tanda tangan dalam header `x-ca-signature` tidak cocok dengan tanda tangan yang dihitung oleh server.

400

Invalid Content-MD5

Header `content-md5` salah.

400

Invalid Date

Offset waktu yang dihitung dari header `date` melebihi `date_offset` yang dikonfigurasi.

413

Request Body Too Large

Badan permintaan melebihi batas ukuran 32 MB.

413

Payload Too Large

Badan permintaan melebihi konfigurasi global `DownstreamConnectionBufferLimits`.

403

Unauthorized Consumer

Pemanggil tidak memiliki izin akses.

Kode contoh (Go)

go
package main
import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)
func generateHMACSignature(toSign string, key string) (string, error) {
	h := hmac.New(sha256.New, []byte(key))
	h.Write([]byte(toSign))
	return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
}
func test(accessKey, secretKey string) {
	body := `{"hello":"world"}`
	h := md5.New()
	h.Write([]byte(body))
	payload := base64.StdEncoding.EncodeToString(h.Sum(nil))
	headers := map[string]string{
		"accept":                 "application/json",
		"content-type":           "application/json",
		"date":                   time.Now().Format("2006-01-02 15:04:05"),
		"x-ca-key":               accessKey,
		"foo":                    "bar",
		"x-ca-signature-headers": "foo",
		"content-md5":            payload,
	}
	sts := strings.Join([]string{"POST", headers["accept"], headers["content-md5"], headers["content-type"], headers["date"], "foo:bar", "/post"}, "\n")
	fmt.Printf("String yang akan ditandatangani adalah: %s\n", strings.ReplaceAll(sts, "\n", "#"))
	sign, _ := generateHMACSignature(sts, secretKey)
	fmt.Printf("String yang ditandatangani adalah: %s\n", sign)
	headers["x-ca-signature"] = sign
	req, _ := http.NewRequest("POST", "http://localhost:8080/post", bytes.NewBufferString(body))
	for k, v := range headers {
		req.Header.Add(k, v)
	}
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("kesalahan membaca badan")
	}
	defer resp.Body.Close()
	fmt.Println("Header adalah sebagai berikut:")
	for k, v := range resp.Header {
		// Jika perhitungan tanda tangan gagal, header respons X-Ca-Error-Message akan berisi string yang akan ditandatangani yang dihitung oleh server. Anda dapat menggunakan ini untuk memecahkan masalah.
		fmt.Printf("  %s: %s\n", k, v)
	}
	respBody, _ := io.ReadAll(resp.Body)
	fmt.Println(string(respBody))
}
func main() {
	test("appKey", "appSecret")
}

Otentikasi kunci API

Permintaan diverifikasi berdasarkan sumber kredensial yang dikonfigurasi. Prosesnya serupa untuk API dan entri rute. Contoh berikut menggunakan entri rute.

Terdapat tiga jenis utama sumber kredensial untuk kunci API:

  1. Sumber kredensial default: `Authorization: Bearer `.

  2. Header Kustom: Masukkan nama parameter header.

  3. Parameter kueri kustom: Masukkan nama parameter kueri.

Sumber kredensial default

Asumsikan permintaan berikut cocok dengan entri rute `abc`. Atur kunci API dalam header permintaan HTTP `Authorization` dan tambahkan awalan `Bearer`. Perhatikan bahwa terdapat spasi antara `Bearer` dan kunci API.

curl  http://xxx.test.com/test -H 'x-api-key: Bearer 2bda943c-ba2b-11ec-ba07-00163e1250b5'

Setel Kunci API di Header Permintaan HTTP

curl  http://xxx.test.com/test -H 'x-api-key: Bearer 2bda943c-ba2b-11ec-ba07-00163e1250b5'

Sumber header kustom

Asumsikan permintaan berikut cocok dengan entri rute `abc`, dan kunci API diatur dalam header permintaan HTTP kustom.

  • Jika entri rute tidak memiliki kebijakan autentikasi dan otorisasi konsumen yang diaktifkan, akses ditolak dengan kesalahan 401.

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5
  • Jika entri rute memiliki kebijakan autentikasi dan otorisasi konsumen yang diaktifkan tetapi tidak diotorisasi, kesalahan 403 dikembalikan.

    curl  http://xxx.test.com/test -H 'x-api-key: 2bda943c-ba2b-11ec-ba07-00163e1250b5'

Parameter kueri kustom

Asumsikan permintaan berikut cocok dengan entri rute `abc`, dan kunci API diatur dalam parameter kueri URL.

  • Jika entri rute tidak memiliki kebijakan autentikasi dan otorisasi konsumen yang diaktifkan, akses ditolak dengan kesalahan 401.

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5
  • Jika entri rute memiliki kebijakan autentikasi dan otorisasi konsumen yang diaktifkan tetapi tidak diotorisasi, kesalahan 403 dikembalikan.

    curl  http://xxx.test.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5

Kode kesalahan terkait

Kode Status HTTP

Pesan Kesalahan

Penyebab

401

Key authentication check failed. Multiple API keys were found in the request.

Anda dapat meminta beberapa kunci API.

401

Key authentication check failed. No API key was found in the request.

Permintaan tidak berisi kunci API.

401

Key authentication check failed. The API key is invalid.

Kunci API tidak diotorisasi untuk mengakses sumber daya.

403

Key authentication check failed. The consumer is unauthorized.

Konsumen tidak memiliki izin akses yang diperlukan.

Referensi

Untuk informasi lebih lanjut, lihat Manajemen otorisasi.