iOS SDK

Prev Next

Classic/VPC 환경에서 이용 가능합니다.

iOS 앱의 보안을 위한 App Safer iOS SDK 사용 방법에 대해 설명합니다. SDK를 설치하고 환경을 구성함으로써 App Safer를 연동할 수 있습니다.

참고

App Safer를 적용하는 전반적인 샘플 코드는 샘플 코드에서 확인해 주십시오.

SDK 설치 및 환경 구성

App Safer에서 제공하는 기능을 이용하려면 먼저 iOS SDK를 설치한 후 환경을 구성해 주십시오. iOS 앱용 App Safer의 라이브러리는 하나의 프레임워크로 구성되어 있으며, 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
이름 설명
initAppSafer AppSafer을 사용하기 위해 초기화
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
  • 매개변수

    매개변수 설명
    delegate AppSaferDelegate가 구현된 인스턴스
    serviceCode App Safer를 이용하기 위한 코드
    네이버 클라우드 플랫폼 사용자는 반드시 '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");
    }