macOS 開發 - entitlements 及使用 Security 判斷授權
阿新 • • 發佈:2019-01-06
文章目錄
簡述
在 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 下面。
更多關於沙盒可參考:
-
天狐:Cocoa開發之沙盒機制及訪問Sandbox之外的檔案
http://www.skyfox.org/cocoa-macos-sandbox.html -
Apple : About Entitlements
核心程式碼 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"];
}