本文介绍了为您的iOS应用集成WAF App防护SDK(以下简称SDK)的操作方法。您必须在应用中集成SDK,才能为应用开启App防护。

使用限制

iOS应用对应的iOS版本是9.0及以上,否则不支持集成App防护SDK。

前提条件

  • 已开通WAF App防护模块且开启了App防护状态开关。

    相关操作,请参见如何为应用开启App防护

  • 已获取iOS应用对应的SDK。

    您开通WAF App防护模块后,可以通过钉钉、工单等方式联系WAF售后技术支持人员获取SDK。

    iOS应用对应的SDK分为IDFA版本和非IDFA版本,对应的SDK文件分别是:
    • AliTigerTally_IDFA.framework
    • AliTigerTally_NOIDFA.framework
    iOS SDK

    如果您的iOS项目中使用了IDFA(广告标识符,全称Identifier for Advertising),推荐您集成AliTigerTally_IDFA版本SDK,否则请使用AliTigerTally_NOIDFA版本SDK。

  • 已获取SDK认证密钥(即appkey)。
    您在Web应用防火墙控制台防护配置 > 网站防护页面开启App防护后,即可单击获取并复制appkey,获取SDK认证密钥。该密钥用于发起SDK初始化请求,需要在集成代码中使用。
    说明 每个阿里云账号拥有唯一的appkey(适用于所有接入WAF防护的域名),且Android和iOS应用集成SDK时都使用该appkey
    App防护
    认证密钥示例:
    ****OpKLvM6zliu6KopyHIhmneb_****u4ekci2W8i6F9vrgpEezqAzEzj2ANrVUhvAXMwYzgY_****vc51aEQlRovkRoUhRlVsf4IzO9dZp6nN_****Wz8pk2TDLuMo4pVIQvGaxH3vrsnSQiK****

背景信息

App防护SDK主要用于对通过App客户端发起的请求进行签名。WAF服务端通过校验App请求签名,识别App业务中的风险、拦截恶意请求,实现App防护的目的。

创建一个测试工程(可选)

您可以直接在真实的iOS工程中集成SDK,或者先创建一个测试工程进行测试,等熟悉操作后,再在真实环境中进行操作。

以Xcode环境为例,新建一个iOS工程,并按照配置向导完成创建。

本文将测试工程命名为TigerTally_sdk_test,创建好的工程目录如下图所示。测试Demo

操作步骤

  1. 使用Xcode打开App工程,进入文件目录。
  2. 将SDK复制到项目中。
    • 非IDFA版本示例无IDFA
    • IDFA版本示例有IDFA
  3. 在项目中添加以下依赖库。
    依赖库 非IDFA版本是否需要 IDFA版本是否需要
    libc++.tbd
    CoreTelephony.framework
    libresolv.9.tbd
    AdSupport.framework
    添加依赖库
  4. 打开编译选项设置(Build Settings),在Other Linker Flags选项中添加-ObjC添加编译选项
  5. 添加集成代码。
    1. 在需要集成SDK的源文件中,添加头文件。
      示例代码:
      • Objective-C语言
        // 非IDFA版本。
        #import <AliTigerTally_NOIDFA/AliTigerTally.h> 
        
        // IDFA版本。
        #import <AliTigerTally_IDFA/AliTigerTally.h>
      • Swift语言
        // 创建头文件。
        #ifndef TigerTally_sdk_Swift_h
        #define TigerTally_sdk_Swift_h
        
        // 非IDFA版本。
        #import <AliTigerTally_NOIDFA/AliTigerTally.h> 
        // IDFA版本。
        #import <AliTigerTally_IDFA/AliTigerTally.h>
        
        #endif /* TigerTally_sdk_Swift_h */
        您需要在编译选项设置(Build Settings)的Objective-C Bridging Header选项中,添加已创建的头文件。添加头文件
    2. 设置用户标识。
      接口定义:
      -(void)setAccount:(NSString*)account

      功能:设置您业务中自定义的终端用户标识,方便您更灵活地配置WAF防护策略。

      接口参数:<account>,NSString*类型,表示标识一个用户的字符串(建议您使用脱敏后的格式)。

      返回值:无。

      示例代码:
      • Objective-C语言
        // testAccount表示用户标识字符串示例。
        // 如果当前登录的用户是游客身份,可以跳过这步,直接调用初始化函数。
        [[AliTigerTally sharedInstance] setAccount:@"testAccount"]; 
      • Swift语言
        // testAccount表示用户标识字符串示例。
        // 如果当前登录的用户是游客身份,可以跳过这步,直接调用初始化函数。
        AliTigerTally.sharedInstance().setAccount("testAccount")
    3. 添加初始化函数。
      接口定义:
      -(bool)initialize:(NSString*)appKey

      功能:初始化SDK,执行一次初始化采集。一次初始化采集表示采集一次终端设备信息,您可以根据业务的不同,重新调用initialize函数进行初始化采集。

      接口参数:<appKey>,NSString*类型,设置成您的SDK认证密钥。

      返回值:bool类型,返回是否初始化成功,true表示成功,false表示失败。

      示例代码:
      • Objective-C语言
        NSString *appKey=@"****OpKLvM6zliu6KopyHIhmneb_****u4ekci2W8i6F9vrgpEezqAzEzj2ANrVUhvAXMwYzgY_****vc51aEQlRovkRoUhRlVsf4IzO9dZp6nN_****Wz8pk2TDLuMo4pVIQvGaxH3vrsnSQiK****";
        if([[AliTigerTally sharedInstance]initialize:appKey]){
            NSLog(@"初始化成功");
         }else{
             NSLog(@"初始化失败");
        }
      • Swift语言
        let binit = AliTigerTally.sharedInstance().initialize("****OpKLvM6zliu6KopyHIhmneb_****u4ekci2W8i6F9vrgpEezqAzEzj2ANrVUhvAXMwYzgY_****vc51aEQlRovkRoUhRlVsf4IzO9dZp6nN_****Wz8pk2TDLuMo4pVIQvGaxH3vrsnSQiK****")
        if(binit){
            NSLog("初始化成功");
        }else{
            NSLog("初始化失败");
        }
    4. 签名请求数据。
      接口定义:
      -(NSString*)vmpSign:(NSData*)inputBody

      功能:对输入的数据进行签名,并且返回签名串。

      接口参数:<inputBody>,NSData*类型,表示待签名的数据体。

      返回值:
      • 正常返回结果:NSString* 类型,返回签名串。
      • 异常返回结果:
        返回结果 说明 建议操作
        you must call initialize 表示您没有调用initialize函数。 请先调用initialize函数初始化SDK,然后再调用vmpSign函数。
        you must input body 表示您没有设置待签名的数据体。 您在调用vmpSign函数时,必须设置要签名的数据体(<inputBody>)。
        NULL 表示初始化未完成,签名失败。 建议您重新调用vmpSign函数。

        如果该问题反复出现,请通过钉钉、工单等方式联系WAF售后技术支持人员获取帮助。

      示例代码:
      说明 示例代码中将签名串定义为wToken
      • Objective-C语言
        if(![[AliTigerTally sharedInstance]initialize:@"xxxxxxxxxxxxxxxxxxxxx"])
        {
                NSLog(@"初始化失败");
                return;
        }
        NSString *signBody =@"hello";
        NSString *wToken= [[AliTigerTally sharedInstance] vmpSign:[signBody dataUsingEncoding:NSUTF8StringEncoding]];
        NSLog(@"wToken== %@",wToken);
      • Swift语言
        if(!AliTigerTally.sharedInstance().initialize("xxxxxxxxxxxxxxxxxxxxx")){
            NSLog("初始化失败");
           return
        } 
        let signBody = "hello"
        var token = AliTigerTally.sharedInstance().vmpSign(signData)
        NSLog(token);
    5. 将签名串添加到协议头,并发送数据到服务器。

      在业务关键事件(例如,客户端登录请求事件)中,将签名串提交到应用服务器。WAF服务端在获取应用服务器收到的请求后,通过解析签名串(wToken)进行风险识别、拦截恶意请求,然后将合法请求转发回源站。

      示例代码:
      • Objective-C语言
        NSURL * url = [NSURL URLWithString:@"https://xxxxxx/test?id=123"];
        NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
        [request setValue: wToken forHTTPHeaderField: @"wToken"];
        request.HTTPMethod=@"post";
        request.HTTPBody=[signBody dataUsingEncoding:NSUTF8StringEncoding];
        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if(error){
                NSLog(@"发送失败%@", error);
            }else
            {
                NSLog(@"发送成功");
            }
        }];
        [dataTask resume];
      • Swift语言
        guard let url = URL(string: "https://xxxxxx/test?id=123") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue(token, forHTTPHeaderField: "wToken")
        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in
            if let data = data {
                do {
                    print("OK")
                } catch {
                    print("ERROR")
                    print(error)
                }
            }
        
        }.resume()
        }