简述
在 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
https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AboutEntitlements.html
核心代码 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"];
}