All Products
Search
Document Center

Web Application Firewall:Integrasi SDK aplikasi iOS

Last Updated:Apr 01, 2026

Integrasikan Web Application Firewall (WAF) App Protection SDK ke dalam aplikasi iOS Anda untuk mengaktifkan penandatanganan permintaan dan perlindungan bot. Setelah integrasi, WAF memverifikasi tanda tangan permintaan guna mendeteksi dan memblokir lalu lintas berbahaya.

Prasyarat

Sebelum memulai, pastikan Anda telah memiliki:

  • Aplikasi iOS yang menjalankan iOS 9.0 atau versi lebih baru (versi sebelumnya tidak didukung)

  • WAF App Protection SDK untuk iOS — ajukan ticket untuk mendapatkannya dari ahli teknis produk

  • Kunci otentikasi SDK (AppKey) — setelah Anda mengaktifkan Bot Management, buka Bot Management > App Protection, lalu klik Obtain and Copy AppKey di daftar aplikasi

image
Paket SDK diberi nama tigertally-X.Y.Z-xxxx-ios.zip (di mana X.Y.Z adalah nomor versi) dan berisi dua file framework serta dua file xcframework. Setiap Akun Alibaba Cloud memiliki satu AppKey yang berlaku untuk semua domain yang dilindungi WAF dan dapat digunakan lintas integrasi Android, iOS, dan HarmonyOS.

Contoh AppKey: **OpKLvM6zliu6KopyHIhmneb_u4ekci2W8i6F9vrgpEezqAzEzj2ANrVUhvAXMwYzgY_vc51aEQlRovkRoUhRlVsf4IzO9dZp6nN_Wz8pk2TDLuMo4pVIQvGaxH3vrsnSQiK**

Pilih versi SDK

SDK iOS tersedia dalam dua versi. Pilih berdasarkan apakah aplikasi Anda menggunakan identifier for advertisers (IDFA):

VersiFramework fileGunakan saat
IDFAAliTigerTally_IDFA.frameworkAplikasi Anda menggunakan IDFA
Non-IDFAAliTigerTally_NOIDFA.frameworkAplikasi Anda tidak menggunakan IDFA

Langkah 1: Buat proyek

Buat proyek iOS baru di Xcode dan selesaikan wizard pengaturan.

image.png

Langkah 2: Tambahkan file framework

Tambahkan framework utama SDK ke proyek Anda. Pilih versi yang sesuai dengan kebutuhan IDFA Anda.

Versi IDFA:

image.png

Versi Non-IDFA:

image.png

Tambahkan framework modul CAPTCHA AliCaptcha.framework ke proyek Anda:

image.png

Tambahkan bundle resource AliCaptcha.bundle ke proyek Anda:

image.png

Langkah 3: Tambahkan pustaka dependensi

Tambahkan pustaka berikut di bawah Link Binary With Libraries pada build phases target Anda:

PustakaVersi IDFAVersi Non-IDFA
libc++.tbdYaYa
libresolv.9.tbdYaYa
CoreTelephony.frameworkYaYa
AdSupport.frameworkYaTidak
AppTrackingTransparency.frameworkYaTidak
image.png

Langkah 4: Konfigurasi flag linker

Di Build Settings, tambahkan -ObjC ke Other Linker Flags:

image.png

Langkah 5: Tambahkan kode integrasi

Impor file header

Versi IDFA:

#import <AliTigerTally_IDFA/AliTigerTally.h>

Versi Non-IDFA:

#import <AliTigerTally_NOIDFA/AliTigerTally.h>

Inisialisasi SDK

Panggil init sekali saat aplikasi dimulai untuk mengumpulkan informasi perangkat. SDK mendukung tiga mode pengumpulan data — pilih salah satu berdasarkan kebutuhan privasi Anda:

ModecollectType nilaiData yang dikumpulkan
LengkapTT_DEFAULTSemua data perangkat
Privasi kustomTT_NO_BASIC_DATA, TT_NO_UNIQUE_DATA, TT_NO_EXTRA_DATA (dapat dikombinasikan dengan |)Data parsial — mengecualikan kategori yang ditentukan
Tanpa privasiTT_NOT_GRANTEDTidak ada bidang privasi (mengecualikan IDFA dan identifier for vendors (IDFV))
Data lengkap meningkatkan deteksi ancaman. Pilih mode yang memenuhi persyaratan kepatuhan privasi Anda sekaligus mengumpulkan data sebanyak mungkin.

Referensi kategori pengumpulan data:

collectType flagMengecualikan
TT_NO_BASIC_DATANama perangkat, versi sistem, resolusi layar
TT_NO_UNIQUE_DATAIDFV dan IDFA
TT_NO_EXTRA_DATAInformasi Wi-Fi terhubung (SSID, BSSID) dan jaringan Wi-Fi terdekat

Signature metode init:

- (int)init:(NSString *)appkey
    collectType:(TTCollectType)type
    options:(NSMutableDictionary *_Nullable)options
    listener:(TTInitListener _Nullable)onInitFinish;

Parameter:

ParameterTipeDeskripsi
appkeyNSStringAppKey Anda dari konsol Bot Management
collectTypeTTCollectTypeMode pengumpulan data (lihat tabel di atas)
optionsNSMutableDictionaryKonfigurasi pelaporan opsional (lihat tabel di bawah). Default: nil
onInitFinishTTInitListenerCallback inisialisasi. Default: nil

Konfigurasi options:

KunciNilaiDeskripsi
IPv60 (default), 10: gunakan IPv4. 1: gunakan IPv6.
Intl0 (default), 10: laporkan dari Tiongkok daratan. 1: laporkan dari luar Tiongkok daratan.
CustomUrlString URLURL server pelaporan kustom (untuk wilayah tertentu, misalnya https://cloudauth-device.us-west-1.aliyuncs.com)
CustomHostString hostnameHost server pelaporan kustom (misalnya cloudauth-device.us-west-1.aliyuncs.com)
Untuk sebagian besar wilayah internasional, atur Intl ke 1. Atur CustomUrl dan CustomHost hanya jika Anda perlu melaporkan ke wilayah tertentu, seperti AS (Silicon Valley).

Nilai kembalian: int0 jika berhasil, negatif jika gagal.

Contoh:

NSString *appKey = @"<your-appkey>";

NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
[options setValue:@"0" forKey:@"IPv6"];  // Gunakan IPv4
[options setValue:@"0" forKey:@"Intl"];  // Laporkan dari Tiongkok daratan
// [options setValue:@"1" forKey:@"Intl"];  // Laporkan dari luar Tiongkok daratan

// Untuk melaporkan ke AS (Silicon Valley):
// [options setValue:@"https://cloudauth-device.us-west-1.aliyuncs.com" forKey:@"CustomUrl"];
// [options setValue:@"cloudauth-device.us-west-1.aliyuncs.com" forKey:@"CustomHost"];

// Pengumpulan data lengkap
if (0 == [[AliTigerTally sharedInstance] init:appKey collectType:TT_DEFAULT options:options listener:nil]) {
    NSLog(@"Inisialisasi berhasil");
} else {
    NSLog(@"Inisialisasi gagal");
}

// Privasi kustom: mengecualikan data perangkat dasar dan tambahan
TTCollectType collectPrivacy = TT_NO_BASIC_DATA | TT_NO_EXTRA_DATA;
[[AliTigerTally sharedInstance] init:appKey collectType:collectPrivacy options:options listener:nil];

// Tanpa privasi: mengecualikan semua bidang privasi
[[AliTigerTally sharedInstance] init:appKey collectType:TT_NOT_GRANTED options:options listener:nil];
Penting

Tunggu minimal 2 detik setelah memanggil init sebelum memanggil vmpSign. Interval ini merupakan rekomendasi, bukan persyaratan wajib, dan bertujuan untuk meningkatkan efektivitas perlindungan SDK. Anda dapat menyesuaikan interval ini sesuai kebutuhan, tetapi interval yang lebih pendek dapat mengurangi kualitas perlindungan.

Tetapkan akun pengguna (opsional)

Panggil setAccount untuk mengaitkan pengenal pengguna yang telah didesensitisasi dengan permintaan. Hal ini memungkinkan kebijakan mitigasi WAF yang lebih granular.

/**
 * Menetapkan akun pengguna.
 * @param account  String yang telah didesensitisasi untuk mengidentifikasi pengguna.
 */
- (void)setAccount:(NSString *)account;

Untuk pengguna tamu, lewati pemanggilan ini dan lanjutkan dengan inisialisasi. Setelah pengguna masuk, panggil setAccount, lalu inisialisasi ulang:

[[AliTigerTally sharedInstance] setAccount:@"<desensitized-user-id>"];

Tandatangani permintaan

Semua contoh menggunakan vmpSign untuk menghasilkan string wtoken dan melampirkannya ke header permintaan wToken.

Penandatanganan default

Gunakan penandatanganan default jika Anda belum memilih opsi penandatanganan kustom di konsol.

Berikan badan permintaan ke vmpSign. Untuk permintaan tanpa badan (seperti GET), berikan nil atau string kosong yang diencode sebagai NSData.

/**
 * Menandatangani data menggunakan teknologi VMP.
 * @param input  Data yang akan ditandatangani (badan permintaan, atau nil untuk badan kosong).
 * @return String wtoken untuk otentikasi permintaan.
 */
- (NSString *)vmpSign:(NSData *)input;

Contoh:

NSString *body = @"hello world";
NSString *wtoken = [[AliTigerTally sharedInstance]
    vmpSign:[body dataUsingEncoding:NSUTF8StringEncoding]];
// Lampirkan wtoken ke header permintaan HTTP "wToken"

Penandatanganan kustom

Gunakan penandatanganan kustom jika Anda telah memilih opsi penandatanganan kustom di konsol. Panggil vmpHash terlebih dahulu untuk menghasilkan whash, lalu berikan nilai whash sebagai input ke vmpSign.

  • Untuk permintaan POST, PUT, PATCH: berikan badan permintaan ke vmpHash

  • Untuk permintaan GET, DELETE: berikan URL lengkap ke vmpHash

Tambahkan nilai whash ke header permintaan ali_sign_whash. Juga atur Custom Signing Field ke ali_sign_whash dalam konfigurasi kebijakan berbasis skenario di konsol Anda.

/**
 * Meng-hash data untuk penandatanganan kustom.
 * @param type   Metode HTTP (TT_GET, TT_POST, TT_PUT, TT_PATCH, TT_DELETE).
 * @param input  Data yang akan di-hash (badan permintaan untuk POST/PUT/PATCH; URL lengkap untuk GET/DELETE).
 * @return String whash.
 */
- (NSString *)vmpHash:(TTRequestType)type input:(NSData *)input;

Contoh permintaan POST:

NSString *body = @"hello world";

// Hasilkan whash dari badan permintaan
NSString *whash = [[AliTigerTally sharedInstance]
    vmpHash:TT_POST input:[body dataUsingEncoding:NSUTF8StringEncoding]];

// Hasilkan wtoken dari whash
NSString *wtoken = [[AliTigerTally sharedInstance]
    vmpSign:[whash dataUsingEncoding:NSUTF8StringEncoding]];

// Lampirkan whash ke header "ali_sign_whash" dan wtoken ke header "wToken"
NSLog(@"whash: %@, wtoken: %@", whash, wtoken);

Contoh permintaan GET:

NSString *url = @"https://tigertally.aliyun.com/apptest";

// Hasilkan whash dari URL lengkap
NSString *whash = [[AliTigerTally sharedInstance]
    vmpHash:TT_GET input:[url dataUsingEncoding:NSUTF8StringEncoding]];

// Hasilkan wtoken dari whash
NSString *wtoken = [[AliTigerTally sharedInstance]
    vmpSign:[whash dataUsingEncoding:NSUTF8StringEncoding]];
URL yang diberikan ke vmpHash harus persis sama dengan URL permintaan akhir. Beberapa framework secara otomatis mengencode karakter Tionghoa atau parameter kueri — verifikasi bahwa tidak ada perbedaan encoding. vmpHash tidak menerima string kosong; untuk permintaan GET, URL harus mencakup path atau parameter kueri.

Tangani verifikasi sekunder

Jika WAF mendeteksi aktivitas mencurigakan, sistem akan mengembalikan tantangan CAPTCHA. Periksa setiap respons dan tampilkan slider CAPTCHA bila diperlukan.

Periksa respons

Berikan cookie respons dan badan respons ke cptCheck setelah setiap permintaan:

/**
 * Memeriksa apakah verifikasi sekunder diperlukan.
 * @param cookie  Semua cookie dari respons (digabung dalam format "key=value;").
 * @param body    Badan respons lengkap.
 * @return 0: lolos. 1: verifikasi sekunder diperlukan.
 */
- (int)cptCheck:(NSString *)cookie body:(NSData *)body;
Header respons mungkin mencakup beberapa bidang Set-Cookie. Gabungkan menjadi format key1=value1;key2=value2; sebelum diberikan ke cptCheck.

Contoh:

NSString *cookie = @"key1=value1;key2=value2;";
NSData *body = /* badan respons */;
int recheck = [[AliTigerTally sharedInstance] cptCheck:cookie body:body];
// recheck == 1: tampilkan slider CAPTCHA

Tampilkan slider CAPTCHA

Saat cptCheck mengembalikan 1, buat dan tampilkan slider TTCaptcha:

/**
 * Membuat slider CAPTCHA untuk verifikasi sekunder.
 * @param view      Tampilan induk.
 * @param option    Konfigurasi slider.
 * @param delegate  Callback untuk hasil verifikasi.
 * @return Objek slider TTCaptcha.
 */
- (TTCaptcha *)cptCreate:(UIView *)view option:(TTOption *)option delegate:(id<TTDelegate>)delegate;

Konfigurasi TTOption:

PropertiTipeDeskripsi
cancelableBOOLIzinkan pengguna menutup slider dengan mengetuk di luar area slider
customUriNSStringPath ke halaman verifikasi kustom (file HTML lokal atau URL remote)
languageNSStringBahasa tampilan (misalnya @"cn" untuk Tionghoa, @"en" untuk Inggris)

Callback TTDelegate:

@protocol TTDelegate <NSObject>
@required
// Dipanggil saat verifikasi berhasil.
- (void)success:(TTCaptcha *)captcha data:(NSString *)data;

// Dipanggil saat verifikasi gagal.
- (void)failed:(TTCaptcha *)captcha code:(NSString *)code;
@end

Contoh:

TTOption *option = [[TTOption alloc] init];
option.language   = @"cn";
option.cancelable = YES;

TTCaptcha *captcha = [[AliTigerTally sharedInstance]
    cptCreate:[self view] option:option delegate:self];
[captcha show];

// Di callback TTDelegate:
- (void)success:(TTCaptcha *)captcha data:(nonnull NSString *)data {
    NSLog(@"Verifikasi berhasil: %@", data);
}

- (void)failed:(TTCaptcha *)captcha code:(nonnull NSString *)code {
    NSLog(@"Verifikasi gagal dengan kode: %@", code);
}

Kode status inisialisasi

KodeKonstantaDeskripsi
0TT_SUCCESSInisialisasi berhasil
-1TT_NOT_INITinit belum dipanggil
-2TT_NOT_PERMISSIONIzin iOS yang diperlukan belum diberikan
-3TT_UNKNOWN_ERRORKesalahan sistem tidak dikenal
-4TT_NETWORK_ERRORKesalahan jaringan
-5TT_NETWORK_ERROR_EMPTYKesalahan jaringan — badan respons kosong
-6TT_NETWORK_ERROR_INVALIDKesalahan jaringan — format respons tidak valid
-7TT_PARSE_SRV_CFG_ERRORGagal mengurai konfigurasi server
-8TT_NETWORK_RET_CODE_ERRORGateway mengembalikan respons kegagalan
-9TT_APPKEY_EMPTYAppKey kosong
-10TT_PARAMS_ERRORKesalahan parameter
-11TT_FGKEY_ERRORKesalahan perhitungan kunci
-12TT_APPKEY_ERRORVersi SDK tidak cocok dengan versi AppKey

Kode kesalahan CAPTCHA

KodeDeskripsi
1001Verifikasi gagal (terjadi pengecualian slider selama atau setelah interaksi pengguna)
1002Pengecualian sistem
1003Kesalahan parameter
1005Verifikasi dibatalkan oleh pengguna
8001Gagal memanggil slider
8002Data verifikasi slider tidak normal
8003Pengecualian internal selama verifikasi slider
8004Kesalahan jaringan

Pemecahan masalah

vmpSign atau vmpHash mengembalikan string kesalahan alih-alih token

Jika whash atau wtoken berisi salah satu string berikut, terjadi kesalahan:

  • "you must call init first"init belum dipanggil sebelum penandatanganan. Panggil init dan tunggu minimal 2 detik sebelum memanggil vmpSign.

  • "you must input correct data" — Data input tidak valid. Periksa bahwa badan permintaan atau URL tidak kosong atau rusak.

  • "you must input correct type" — Tipe metode HTTP yang diberikan ke vmpHash salah.

Ketidaksesuaian encoding URL dalam penandatanganan permintaan GET

Jika whash untuk permintaan GET ditolak, URL yang diberikan ke vmpHash mungkin tidak sesuai dengan URL permintaan aktual. Beberapa framework jaringan secara otomatis melakukan percent-encoding pada parameter kueri atau karakter Tionghoa. Catat kedua URL tersebut dan bandingkan karakter per karakter.

Inisialisasi gagal dengan TT_NETWORK_ERROR (-4)

Periksa apakah perangkat memiliki akses jaringan dan domain pelaporan dapat dijangkau. Jika Anda melakukan deployment di luar Tiongkok daratan, atur Intl ke 1 dalam dictionary options. Untuk titik akhir wilayah tertentu, atur CustomUrl dan CustomHost.

Contoh lengkap

Contoh berikut menunjukkan alur integrasi lengkap — inisialisasi, penandatanganan permintaan, pemeriksaan verifikasi sekunder, dan tampilan CAPTCHA.

#import "DemoController.h"
#if __has_include(<AliTigerTally_NOIDFA/AliTigerTally_NOIDFA.h>)
    #import <AliTigerTally_NOIDFA/AliTigerTally_NOIDFA.h>
#else
    #import <AliTigerTally_IDFA/AliTigerTally_IDFA.h>
#endif

@interface DemoController () <TTDelegate>
@end

static NSString *kAppHost = @"******";
static NSString *kAppUrl  = @"******";
static NSString *kAppkey  = @"******";

@implementation DemoController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self doTest];
}

- (void)doTest {
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        // Langkah 1: Inisialisasi SDK
        NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
        // [options setValue:@"1" forKey:@"Intl"];  // Hapus komentar untuk luar Tiongkok daratan
        int code = [[AliTigerTally sharedInstance] init:kAppkey collectType:TT_DEFAULT options:options listener:nil];
        NSLog(@"tigertally init: %d", code);

        // Langkah 2: Tunggu minimal 2 detik sebelum menandatangani
        [NSThread sleepForTimeInterval:2.0];

        // Langkah 3: Tandatangani permintaan (contoh penandatanganan kustom)
        NSString *body = @"hello world";
        NSString *whash = [[AliTigerTally sharedInstance]
            vmpHash:TT_POST input:[body dataUsingEncoding:NSUTF8StringEncoding]];
        NSString *wtoken = [[AliTigerTally sharedInstance]
            vmpSign:[whash dataUsingEncoding:NSUTF8StringEncoding]];
        NSLog(@"tigertally vmp — whash: %@, wtoken: %@", whash, wtoken);

        // Untuk penandatanganan default (opsi penandatanganan kustom tidak dipilih):
        // wtoken = [[AliTigerTally sharedInstance] vmpSign:[body dataUsingEncoding:NSUTF8StringEncoding]];

        // Langkah 4: Kirim permintaan dan periksa verifikasi sekunder
        [self doPost:kAppUrl host:kAppHost whash:whash wtoken:wtoken
            body:[body dataUsingEncoding:NSUTF8StringEncoding]
            callback:^(NSInteger code, NSString *cookie, NSData *body) {
                int check = [[AliTigerTally sharedInstance] cptCheck:cookie body:body];
                NSLog(@"hasil pemeriksaan captcha: %d", check);
                if (check == 0) return;
                // Verifikasi sekunder diperlukan — tampilkan CAPTCHA di thread utama
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    [self doShow];
                }];
            }];
    }];
    [thread start];
}

- (void)doShow {
    TTOption *option = [[TTOption alloc] init];
    option.language   = @"cn";
    option.cancelable = YES;
    TTCaptcha *captcha = [[AliTigerTally sharedInstance]
        cptCreate:[self view] option:option delegate:self];
    [captcha show];
}

- (void)doPost:(NSString *)url host:(NSString *)host
        whash:(NSString *)whash wtoken:(NSString *)wtoken
        body:(NSData *)body callback:(void(^)(NSInteger code, NSString *cookie, NSData *body))callback {
    NSURL *requestUrl = [NSURL URLWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestUrl
        cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    [request setValue:@"text/x-markdown" forHTTPHeaderField:@"Content-Type"];
    [request setValue:host forHTTPHeaderField:@"HOST"];
    [request setValue:wtoken forHTTPHeaderField:@"wToken"];
    if (whash) {
        [request setValue:whash forHTTPHeaderField:@"ali_sign_whash"];
    }
    request.HTTPMethod = @"POST";
    request.HTTPBody = body;

    NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession]
        dataTaskWithRequest:request
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            if (error) {
                callback(-1, nil, [[error description] dataUsingEncoding:NSUTF8StringEncoding]);
                return;
            }
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSMutableString *cookies = [[NSMutableString alloc] init];
            for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
                if ([url containsString:[cookie domain]]) {
                    [cookies appendFormat:@"%@=%@;", [cookie name], [cookie value]];
                }
            }
            callback(httpResponse.statusCode, cookies, data);
        }];
    [dataTask resume];
}

#pragma mark - TTDelegate

- (void)failed:(TTCaptcha *)captcha code:(nonnull NSString *)code {
    NSLog(@"captcha gagal: %@", code);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
        message:code preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)success:(TTCaptcha *)captcha data:(nonnull NSString *)data {
    NSLog(@"captcha berhasil: %@", data);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
        message:data preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

@end