Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 以编程方式访问应用程序标识符前缀_Iphone_Objective C_Ios_Cocoa Touch_Ipad - Fatal编程技术网

Iphone 以编程方式访问应用程序标识符前缀

Iphone 以编程方式访问应用程序标识符前缀,iphone,objective-c,ios,cocoa-touch,ipad,Iphone,Objective C,Ios,Cocoa Touch,Ipad,如何以编程方式访问捆绑包种子ID/团队ID/应用程序标识符前缀字符串?(据我所知,这些都是一回事) 我正在使用UICKeychainStore密钥链包装器跨多个应用程序持久化数据。每个应用程序在其授权列表中都有一个共享密钥链访问组,并共享相同的配置文件。默认情况下,keychain服务使用plist中的第一个访问组作为保存数据的访问组。当我调试UICKeychainStore时,它看起来像“AS234SDG.com.myCompany.SpecificApp”。我想将访问组设置为“AS234SD

如何以编程方式访问捆绑包种子ID/团队ID/应用程序标识符前缀字符串?(据我所知,这些都是一回事)


我正在使用UICKeychainStore密钥链包装器跨多个应用程序持久化数据。每个应用程序在其授权列表中都有一个共享密钥链访问组,并共享相同的配置文件。默认情况下,keychain服务使用plist中的第一个访问组作为保存数据的访问组。当我调试UICKeychainStore时,它看起来像“AS234SDG.com.myCompany.SpecificApp”。我想将访问组设置为“AS234SDG.com.myCompany.SharedStuff”,但我似乎找不到如何以编程方式获取访问组的“AS234SDG”字符串,并且希望尽可能避免硬编码

您可以通过查看现有密钥链项目的访问组属性(即
kSecAttrAccessGroup
)以编程方式检索捆绑包种子ID。在下面的代码中,我查找现有的KeyChain条目,如果它不存在,则创建一个。一旦我有了一个密钥链条目,我就从中提取访问组信息,并返回访问组的第一个组件,以“.”(句号)分隔,作为包种子ID

+(NSString*)bundleseId{
NSString*tempAccountName=@“bundleseEd”;
NSDictionary*查询=@{
(uuu桥NSString*)kSecClass:(uuu桥NSString*)kSecClassGenericPassword,
(_桥NSString*)kSecAttrAccount:tempAccountName,
(uu桥NSString*)kSecAttrService:@“”,
(uu桥NSString*)kSecReturnAttributes:(uu桥NSNumber*)kCFBooleanTrue,
};
cfyref结果=零;
OSStatus status=SecItemCopyMatching((uu桥CFDictionaryRef)查询,(CFTypeRef*)和结果);
如果(状态==errSecItemNotFound)
status=SecItemAdd((uu桥CFDictionaryRef)查询,(CFTypeRef*)和结果;
如果(状态!=errSecSuccess){
返回零;
}
status=SecItemDelete((uu桥CFDictionaryRef)查询);//删除临时项
NSDictionary*dict=(\u桥\u传输NSDictionary*)结果;
NSString*accessGroup=dict[(桥NSString*)kSecAttrAccessGroup];
NSArray*components=[accessGroup componentsSeparatedByString:@.”;
NSString*bundleSeedID=[[components objectEnumerator]nextObject];
返回bundleSeedID;
}

这是一个很好的问题,但要实现您的目标,可能有一个解决方案 它不需要检索捆绑种子ID

由此可知,您使用的钥匙链包装器大致相同:

默认情况下,它将选择您的应用程序中指定的第一个访问组 编写时列出authentications.plist,并将在所有 未指定时访问组

然后将在授予访问权限的所有组中搜索密钥。
因此,为了解决您的问题,您可以将所有捆绑应用程序的访问组添加到您的授权中。plist不使用“共享内容”组,而是将$(CbundleIdentifier)作为您的第一个密钥链组(您的密钥链包装器将在该组中写入)您已经设置好了

Info.plist可以有您自己的信息,如果您使用
$(AppIdentifierPrefix)
写入一个值,它将在构建阶段替换为真正的应用程序标识符前缀

那么,试试这个:

在Info.plist中,添加关于应用程序标识符前缀的信息

<key>AppIdentifierPrefix</key>
<string>$(AppIdentifierPrefix)</string>
和斯威夫特:

let appIdentifierPrefix =
    Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String

请注意,
appIdentifierPrefix
以句点结束;e、 g.
AS234SDG.

在swift3:中(基于@Hiron解决方案)

只要一句话:

var appIdentifierPrefix = Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String
鉴于此,请在Info.plist中添加以下键值属性:

关键字:AppIdentifierPrefix


字符串值:$(AppIdentifierPrefix)

以下是@David H answer的Swift版本:

static func bundleSeedID() -> String? {
        let queryLoad: [String: AnyObject] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "bundleSeedID" as AnyObject,
            kSecAttrService as String: "" as AnyObject,
            kSecReturnAttributes as String: kCFBooleanTrue
        ]

        var result : AnyObject?
        var status = withUnsafeMutablePointer(to: &result) {
            SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
        }

        if status == errSecItemNotFound {
            status = withUnsafeMutablePointer(to: &result) {
                SecItemAdd(queryLoad as CFDictionary, UnsafeMutablePointer($0))
            }
        }

        if status == noErr {
            if let resultDict = result as? [String: Any], let accessGroup = resultDict[kSecAttrAccessGroup as String] as? String {
                let components = accessGroup.components(separatedBy: ".")
                return components.first
            }else {
                return nil
            }
        } else {
            print("Error getting bundleSeedID to Keychain")
            return nil
        }
    }

我不知道我是否理解你的意思,但这是不是NSString*bundleIDStr=[[[NSBundle mainBundle]infoDictionary]objectForKey:@“CbundleIdentifier”];你在找?那将返回“com.myCompany.SpecificApp”-我在找“AS234SDG”前缀。哦,我知道你现在在问什么了…这是一个很好的问题。我也找不到这个。只是好奇,你是怎么想到用“bundleSeedID”作为kSecAttrAccount的?@RajPara:这只是我随机选择的一个值。如果需要,可以将其更改为“com.acme.bundleSeedID”。关键是在KeyChain中创建一个条目,并将其读回,然后从访问组信息中提取包种子id。这是唯一的解决方案吗?它可以工作,但好奇的是,如果没有其他方法。@orange80:您可以打开“embedded.mobileprovision”文件来提取应用程序ID。但是,由于它封装在CMS结构中,而且CMS api在iOS上不公开,您可以使用以下选项提取plist有效负载:1.)执行一些搜索和替换预处理以剥离CMS标头/签名,2.)嵌入OpenSSL并使用其CMS api提取有效负载,3.)阅读CMS规范并自行构建有效负载提取器。另外,这里还有另一个可能的解决方案(我不知道它是否有效):这个解决方案似乎不再有效了——至少在模拟器中的iOS 7上不行。这似乎是最好的方法。您甚至可以按照权利中显示的方式存储完整值,例如,
$(AppIdentifierPrefix)com.MyCompany.MyApp
,然后直接使用该值,无需进一步修改。同意这是首选。标记为答案的编程方法在2012年可能还不错,但我发现2015年在iOS 8上的代码运行不一致。这应该是实现这一点的首选方法。如果启用了数据保护并撕碎了密钥链访问组,那么使用安全框架检索它会出现一些问题。这在XCode 5.1.1上对我不起作用。$(AppIdentifierPrefix)只返回空白。在packaging build options中打开preprocess info.plist设置没有任何区别。XCode 8 beta已经破坏了这一点
static func bundleSeedID() -> String? {
        let queryLoad: [String: AnyObject] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "bundleSeedID" as AnyObject,
            kSecAttrService as String: "" as AnyObject,
            kSecReturnAttributes as String: kCFBooleanTrue
        ]

        var result : AnyObject?
        var status = withUnsafeMutablePointer(to: &result) {
            SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
        }

        if status == errSecItemNotFound {
            status = withUnsafeMutablePointer(to: &result) {
                SecItemAdd(queryLoad as CFDictionary, UnsafeMutablePointer($0))
            }
        }

        if status == noErr {
            if let resultDict = result as? [String: Any], let accessGroup = resultDict[kSecAttrAccessGroup as String] as? String {
                let components = accessGroup.components(separatedBy: ".")
                return components.first
            }else {
                return nil
            }
        } else {
            print("Error getting bundleSeedID to Keychain")
            return nil
        }
    }