iOS SDK
    • PDF

    iOS SDK

    • PDF

    Article Summary

    Classic/VPC環境で利用できます。

    iOSアプリのセキュリティのための App Safer iOS SDKの使用方法について説明します。SDKをインストールして環境を構成することで、App Saferを連携できます。

    参考

    App Saferを適用する全般的なサンプルコードは、サンプルコードでご確認ください。

    SDKのインストールおよび環境設定

    App Saferで提供する機能を利用するには、まず iOS SDKをインストールした後、環境を設定します。iOSアプリ用の App Saferのライブラリは1つのフレームワークで構成されており、Bitcode Enable/Disable環境のいずれもサポートします。設定方法は、次の通りです。

    参考

    Xcode 8.0以上の環境でビルドすることをお勧めします。

    1. ダウンロードした SDKを任意のディレクトリで圧縮を解凍します。
    2. プロジェクトの Bitcode設定を確認します。
      • パス: Build Settings > Build Options > Enable Bitcode
    3. App Saferフレームワークをプロジェクトに追加します。
      • パス: File > Add Files to "Your Project"... > Options > Copy items if needed選択 > AppSaferFramework.framework選択 > Addクリック
    4. Swiftを使う場合、Objective-Cとの互換性のために Bridging Headerを作成します。
      • ヘッダファイル作成: File > New File... > Header File選択 > プロジェクトのルート位置にファイル名 「AppSaferFramework-Bridging-Header.h」に設定
      • ヘッダファイルをビルド設定に追加: Build Settings > Swift Compiler - General > Objective-C Bridging Header > AppSaferFramework-Bridging-Header.hで次のコードを入力
        #ifndef AppSaferFramework_Bridging_Header_h
        #define AppSaferFramework_Bridging_Header_h
        
        #import <AppSaferFramework/AppSaferFramework.h>
        
        #endif /* AppSaferFramework_Bridging_Header_h */
        

    デバッグ防止機能を適用

    デバッグ防止機能は、SDKをインストールすると自動的に適用されます。もしデバッグが必要な場合、App Safer SDKを一時的に適用解除した状態で使用します。

    キャプチャ遮断および検出機能の適用

    App Safer SDKで提供するアプリプレビュー画面保護、スクリーンショット検出、録画およびミラーリング時の画面保護機能を適用するには、APIを呼び出す必要があります。

    • iOS 13.0未満: AppDelegateでアプリのライフサイクルに合わせて App Safer APIを呼び出し
    • iOS 13.0以上: SceneDelegateでアプリのライフサイクルに合わせて App Safer APIを呼び出し

    APIを呼び出すユースケースは、次の通りです。
    selectorを登録すると、キャプチャイベントの検出時に callbackを受信して希望する動作を実行できます。

    AppDelegate (Swift)
    import UIKit
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        @objc func didDetectCapture() -> Void  {
            print("[DETECT] Detected Screenshot in AppDelegate");
        }
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture))
            return true
        }
    
        func applicationWillResignActive(_ application: UIApplication) {
            AppSafer.preventScreenshot(window, isInvisible: 0)
        }
    
        func applicationDidEnterBackground(_ application: UIApplication) {
            AppSafer.preventScreenshot(window, isInvisible: 1)
        }
    
        func applicationWillEnterForeground(_ application: UIApplication) {
            AppSafer.preventScreenshot(window, isInvisible: 0)
        }
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            AppSafer.preventScreenshot(window, isInvisible: 1)
        }
    }
    
    AppDelegate (Objective-C)
    #import "AppDelegate.h"
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @interface AppDelegate ()
    @end
    
    @implementation AppDelegate
    
    - (void)didDetectCapture {
        NSLog(@"[DETECT] Detected Screenshot in AppDelegate");
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions {
        [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)];
        
        return YES;
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application {
        [AppSafer preventScreenshot:_window isInvisible:false];
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application {
        [AppSafer preventScreenshot:_window isInvisible:false];
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application {
        [AppSafer preventScreenshot:_window isInvisible:true];
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        [AppSafer preventScreenshot:_window isInvisible:true];
    }
    @end
    
    SceneDelegate (Swift)
    import UIKit
    import SwiftUI
    
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
        var window: UIWindow?
    
        @objc func didDetectCapture() -> Void  {
            print("[DETECT] Detected Screenshot in AppDelegate");
        }
        
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
            let contentView = ContentView()
    
            if let windowScene = scene as? UIWindowScene {
                let window = UIWindow(windowScene: windowScene)
                window.rootViewController = UIHostingController(rootView: contentView)
                self.window = window
                window.makeKeyAndVisible()
                
                AppSafer.registerScreenProtectionObserver(window, observer: self, selector: #selector(didDetectCapture))
            }
        }
    
        func sceneDidBecomeActive(_ scene: UIScene) {
            AppSafer.preventScreenshot(window, isInvisible: 0)
        }
    
        func sceneWillResignActive(_ scene: UIScene) {
            AppSafer.preventScreenshot(window, isInvisible: 1)
        }
    
        func sceneWillEnterForeground(_ scene: UIScene) {
            AppSafer.preventScreenshot(window, isInvisible: 0)
        }
    
        func sceneDidEnterBackground(_ scene: UIScene) {
            AppSafer.preventScreenshot(window, isInvisible: 1)
        }
    }
    
    
    SceneDelegate (Objective-C)
    #import "SceneDelegate.h"
    #import <AppSaferFramework/AppSaferFramework.h>
    
    @interface SceneDelegate ()
    @end
    
    @implementation SceneDelegate
    
    - (void)didDetectCapture {
        NSLog(@"[DETECT] Detected Screenshot in SceneDelegate");
    }
    
    - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)) {
        [AppSafer registerScreenProtectionObserver:_window observer:self selector:@selector(didDetectCapture)];
    }
    
    - (void)sceneWillEnterForeground:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
        [AppSafer preventScreenshot:_window isInvisible:false];
    }
    
    - (void)sceneDidBecomeActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
        [AppSafer preventScreenshot:_window isInvisible:false];
    }
    
    - (void)sceneWillResignActive:(UIScene *)scene API_AVAILABLE(ios(13.0)) {
        [AppSafer preventScreenshot:_window isInvisible:true];
    }
    
    - (void)sceneDidEnterBackground:(UIScene *)scene API_AVAILABLE(ios(13.0))  {
        [AppSafer preventScreenshot:_window isInvisible:true];
    }
    
    @end
    

    提供 API

    App Safer APIは2つのパッケージで提供され、各パッケージで呼び出せる APIは、次の通りです。

    • AppSafer
    名前説明
    initAppSaferAppSaferを使用するために初期化
    checkTamperingリアルタイムセキュリティ検出
    • Jailbreak検出
    • Simulator検出
    • Debugging検出
    • Memory Tampered検出
    • Unauthorized Signature検出
    setUserIdユーザー識別子設定
    • AppSaferDelegate
      • 非同期で動作する Callback関数です。
      • 結果処理は AppSaferDelegateを通じて委任されます。
      • 検査結果を受け取るためには AppSaferDelegateを実装した後、initAppSafer関数を使って登録する必要があります。
      • Swiftを使用する場合、structではない classに実装する必要があり、AppSaferDelegateと NSObjectをすべて追加する必要があります。
    名前要否説明
    appSaferDidInitFinish必須App Saferの初期化結果確認
    appSaferDidCheckTamperingFinish必須checkTampering関数の実行結果確認
    appSaferDetectedJailbreak任意デバイスの脱獄行為検出時に呼び出し
    appSaferDetectedSimulator任意デバイスが仮想マシンで実行中であることを検出時に呼び出し
    appSaferDetectedDebugging任意デバッグ行為検出時に呼び出し
    appSaferDetectedMemoryTampered任意アプリのメモリ改ざん検出時に呼び出し

    initAppSafer

    App Saferは初期化に成功することで使用できるようになります。App Saferを初期化するには、以下のコードを使用します。
    ログの送信に必要な情報およびグローバル変数として使われる変数が初期化されます。

    • 初期化の成否を受け取るためには、AppSaferDelegateを実装する必要があります。
    func initAppSafer(_ delegate: AppSaferDelegate!, serviceCode: String!, key appsaferKey: String!) -> Int32
    
    - (int) initAppSafer:(id<AppSaferDelegate>)delegate serviceCode:(NSString *)serviceCode key:(NSString *)appsaferKey
    
    • パラメータ

      パラメータ説明
      delegateAppSaferDelegateが実装されたインスタンス
      serviceCodeApp Saferを利用するためのコード
      NAVERクラウドプラットフォームのユーザーは必ず「ncloud」を転送
      appsaferKeyコンソールでアプリ登録時に作成された App Safer Key値
    • 戻り値

      戻り値説明
      SUCCESS(0)成功
      FAIL(-1)失敗
    • ユースケース

      struct ContentView: View {
          func initAppSaferExample() {
             // APP_SAFER_KEY generated when registering an app to the Console
             let result = AppSafer().initAppSafer(AppSaferDelegator.delegator, serviceCode: "ncloud", key: "<APP_SAFER_KEY>")
      
             NSLog("initAppSafer() result: %d", result);
      
             if(result == SUCCESS) {
                   // init success
             } else if(result == FAIL) {
                   // init fail
             }
          }
      
          var body: some View {
             Button("initAppSafer") {
                   initAppSaferExample()
             }
          }
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (IBAction)initAppSaferExample:(id)sender {
          AppSafer *appSafer = [[AppSafer alloc] init];
      
          int res = FAIL;
          if(appSafer != nil) {
             // APP_SAFER_KEY generated when registering an app to the Console
             res = [appSafer initAppSafer:self serviceCode:@"ncloud" key:@"<APP_SAFER_KEY>"];
      
             NSLog(@"initAppSafer() result: %d", res);
      
             if(res == SUCCESS) {
                   // init success
             }
          }
      }
      

    checkTampering

    リアルタイムセキュリティ検出機能を実行するには、以下のコードを使用します。

    func checkTampering()
    
    - (int)checkTampering
    
    • 戻り値

      戻り値説明
      SUCCESS(0)検査開始成功
      FAIL(-1)検査開始失敗
      BLOCK(2)セキュリティポリシーの違反により遮断
      BEFOREINIT(3)App Saferが初期化されない
    • ユースケース

      struct ContentView: View {
          func checkTamperingExample() {
              let result = AppSafer().checkTampering()
      
              switch(result) {
              case FAIL:
                  print("Failed to check tampering")
                  break
              case SUCCESS:
                  print("Check Tampering Success")
                  break
              case BLOCK:
                  print("Device is blocked")
                  break
              case BEFOREINIT:
                  print("AppSafer is not initialized")
                  break
              default:
                  break
              }
          }
      
          var body: some View {
              Button("checkTampering") {
                  checkTamperingExample()
              }
          }
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (IBAction)checkAppSafer:(id)sender {
          AppSafer *appSafer = [[AppSafer alloc] init];
      
          if(appSafer != nil) {
              int res = [appSafer checkTampering];
      
              switch(res) {
                  case FAIL:
                      NSLog(@"Failed to check tampering");
                      break;
                  case SUCCESS:
                      NSLog(@"Check Tampering Success");
                      break;
                  case BLOCK:
                      NSLog(@"Device is blocked");
                      break;
                  case BEFOREINIT:
                      NSLog(@"AppSafer is not initialized");
                      break;
              }
          } else {
              NSLog(@"AppSafer is nil");
          }
      }
      
      @end
      

    setUserId

    初期化および検出イベントの発生時に App Saferサーバに送信されるログにユーザー識別子を含むには、以下のコードを使用します。

    func setUserId(_ userId: String!) -> Int32
    
    - (int)setUserId:(NSString *)userId
    
    • パラメータ

      パラメータ説明
      userIdユーザー識別子
    • 戻り値

      戻り値説明
      SUCCESS(0)設定成功
      FAIL(-1)設定失敗
    • ユースケース

      struct ContentView: View {
          func setUserIdExample(_ userId: String) {
             print("setUserId(\(userId))")
      
             let result = AppSafer().setUserId(userId)
      
             switch(result) {
             case FAIL:
                   print("Failed to set userId: \(userId)")
                   break
             case SUCCESS:
                   print("setUserId() Success: \(userId)")
                   break
             default:
                   break
             }
          }
      
          var body: some View {
             Button("setUserId") {
                   setUserIdExample("ExampleUserId")
             }
          }
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (IBAction)setUserId:(id)sender {
          AppSafer *appSafer = [[AppSafer alloc] init];
      
          if(appSafer != nil) {
             NSLog(@"setUserId(%@)", [self.useridText text]);
      
             int res = [appSafer setUserId:[self.useridText text]];
      
             switch(res) {
                   case FAIL:
                      NSLog(@"Failed to set userId");
                      break;
                   case SUCCESS:
                      NSLog(@"setUserId Success");
                      break;
             }
          } else {
             NSLog(@"AppSafer is nil");
          }
      }
      

    appSaferDidInitFinish

    initAppSafer関数の呼び出し後、初期化結果を転送するために下記の関数が呼び出されます。

    func appSaferDidInitFinish(_ result: Int32)
    
    - (void)appSaferDidInitFinish:(int)result
    
    • パラメータ

      パラメータ説明
      SUCCESS(0)初期化成功
      FAIL(-1)初期化失敗
      BLOCK(2)セキュリティポリシー違反により遮断
    • ユースケース

      func appSaferDidInitFinish(_ result: Int32) {
          print("appSaferDidInitFinish result: \(result)");
          if(result == BLOCK) {
             print("Device is blocked!");
             // add to exit application logic
          }
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDidInitFinish:(NSUInteger)result msg:(NSString *)message {
          NSLog(@"appSaferDidInitFinish result: %d", result);
          if(result == BLOCK) {
             NSLog(@"Device is blocked!");
             // add to exit application logic
          }
      }
      

    appSaferDidCheckTamperingFinish

    checkTampering関数の実行結果を転送するために下記の関数が呼び出されます。

    func appSaferDidCheckTamperingFinish(_ result: Int32)
    
    - (void)appSaferDidCheckTamperingFinish:(int)result
    
    • パラメータ

      パラメータ説明
      FAIL(-1)検査失敗
      SAFE(0)イベントが検出されない
      DETECT(1)イベント検出
      BLOCK(2)遮断済み
    • ユースケース

      func appSaferDidCheckTamperingFinish(_ result: Int32) {
          print("appSaferDidCheckTamperingFinish result: " + (
                   result == FAIL   ? "FAIL" :
                   result == SAFE   ? "SAFE" :
                   result == DETECT ? "DETECT" :
                   result == BLOCK  ? "BLOCK": "UNKNOWN"))
      
          if(result == BLOCK) {
             print("Device is blocked!")
             // add to exit application logic
          }
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDidCheckTamperingFinish:(int)result {
          NSLog(@"appSaferDidCheckTamperingFinish result: %@",
                result == FAIL   ? @"FAIL" :
                result == SAFE   ? @"SAFE" :
                result == DETECT ? @"DETECT" :
                result == BLOCK  ? @"BLOCK": @"UNKNOWN");
      
          if(result == BLOCK) {
             NSLog(@"Device is blocked!");
             // add to exit application logic
          }
      }
      

    appSaferDetectedJailbreak

    デバイスの脱獄が検出されると、以下の関数が呼び出されます。checkTampering関数の動作が完了していない場合でも、結果を受け取りたいときに使用できます。

    func appSaferDetectedJailbreak()
    
    - (void)appSaferDetectedJailbreak
    
    • ユースケース

      func appSaferDetectedJailbreak() {
          print("[DETECT] appSaferDetectedJailbreak");
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDetectedJailbreak {
          NSLog(@"[DETECT] appSaferDetectedJailbreak");
      }
      

    appSaferDetectedSimulator

    アプリが仮想マシンで実行中であることが検出されると、以下の関数が呼び出されます。checkTampering関数の動作が完了していない場合でも、結果を受け取りたいときに使用できます。

    func appSaferDetectedSimulator()
    
    - (void)appSaferDetectedSimulator
    
    • ユースケース

      func appSaferDetectedSimulator() {
          print("[DETECT] appSaferDetectedSimulator");
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDetectedSimulator {
          NSLog(@"[DETECT] appSaferDetectedSimulator");
      }
      

    appSaferDetectedDebugging

    デバイスでデバッグが検出されると、以下の関数が呼び出されます。checkTampering関数の動作が完了していない場合でも、結果を受け取りたいときに使用できます。

    func appSaferDetectedDebugging()
    
    - (void)appSaferDetectedDebugging
    
    • ユースケース

      func appSaferDetectedDebugging() {
          print("[DETECT] appSaferDetectedDebugging");
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDetectedDebugging {
          NSLog(@"[DETECT] appSaferDetectedDebugging");
      }
      

    appSaferDetectedMemoryTampered

    メモリ改ざんが検出されると、以下の関数が呼び出されます。checkTampering関数の動作が完了していない場合でも、結果を受け取りたいときに使用できます。

    func appSaferDetectedMemoryTampered()
    
    - (void)appSaferDetectedMemoryTampered
    
    • ユースケース

      func appSaferDetectedMemoryTampered() {
          print("[DETECT] appSaferDetectedMemoryTampered");
      }
      
      #import <AppSaferFramework/AppSaferFramework.h>
      
      @implementation ViewController
      
      - (void)appSaferDetectedMemoryTampered {
          NSLog(@"[DETECT] appSaferDetectedMemoryTampered");
      }
      

    この記事は役に立ちましたか?

    Changing your password will log you out immediately. Use the new password to log back in.
    First name must have atleast 2 characters. Numbers and special characters are not allowed.
    Last name must have atleast 1 characters. Numbers and special characters are not allowed.
    Enter a valid email
    Enter a valid password
    Your profile has been successfully updated.