1. 程式人生 > >macOS 開發 - entitlements 及使用 Security 判斷授權

macOS 開發 - entitlements 及使用 Security 判斷授權

文章目錄


簡述

在 xcode 中 Capabilities 部分勾選內容(不只是沙盒),就會自動生成 projectname.entitlements 檔案。
這個檔案是一個 plist 型別檔案, 其中的鍵對應的是 Capabilities 中勾選的內容。這裡的鍵可以複製出來,作為下面程式判斷的key。
可以觀察,鍵值對是非常細膩的。

常見的鍵如:
com.apple.developer.ubiquity-kvstore-identifier


com.apple.security.application-groups
com.apple.developer.icloud-container-identifiers


關閉 App Sandbox 時,相關的鍵值對也會消失。
不免產一個疑問,為什麼 App Sandbox 下的選項,不歸到 App Sandbox 下面。

在這裡插入圖片描述


更多關於沙盒可參考:


核心程式碼 SecRequirementCreateWithStringAndErrors

#import <Security/CodeSigning.h>

+ (BOOL) hasEntitlement:(NSString*)entitlement
{
    BOOL result = NO;
    CFErrorRef errors = NULL;
    SecCodeRef code = NULL;
    SecRequirementRef requirement = NULL;
    OSStatus status = errSecSuccess;
    
    status = SecCodeCopySelf(kSecCSDefaultFlags, &code);
    if (status == errSecSuccess)
    {
        NSString *requirementString = [NSString stringWithFormat:@"entitlement[\"%@\"] exists", entitlement];
        NSLog(@"\n\n----------\nrequirementString : %@",requirementString);
        //entitlement["com.apple.security.app-sandbox"] exists
        
        status = SecRequirementCreateWithStringAndErrors((__bridge CFStringRef)requirementString, kSecCSDefaultFlags, &errors, &requirement);
        if (status == errSecSuccess)
        {
            status = SecCodeCheckValidity(code, kSecCSDefaultFlags, requirement);
            if (status == errSecSuccess){
                
                result = YES;
                
                NSLog(@"CheckValidity success");  //授權成功
                
            }else{
                NSLog(@"CheckValidity failed : %d",status);
            }
        }else{
            
            NSLog(@"SecRequirementCreate failed : %d",status);  //如果沒有授權
            
            if(errors)
            {
                CFDictionaryRef errDict = CFErrorCopyUserInfo(errors);
                NSLog(@"error: %@", (NSDictionary*)CFBridgingRelease(errDict));
                (void)(CFRelease(errors)), errors = NULL;
            }
        }
    }else{
        NSLog(@"SecCodeCopySelf failed : %d",status);
    }
    
   
    if(!result)
        NSLog(@"Entitlement NOT present: %@", entitlement);  //沒有Entitlement 檔案
    
    if(code)
        CFRelease(code);
    if(requirement)
        CFRelease(requirement);
    
    return result;
}



呼叫方法


+ (BOOL) hasNetworkClientEntitlement {
	return [self hasEntitlement:@"com.apple.security.network.client"];
}

+ (BOOL) hasNetworkServerEntitlement {
	return [self hasEntitlement:@"com.apple.security.network.server"];
}