±¾ÎÄÊÇiOS7ϵÁÐÎÄÕµÚһƪÎÄÕ£¬Ö÷Òª½éÉÜʹÓÃKeyChain±£´æºÍ»ñÈ¡APPÊý¾Ý£¬½â¾öiOS7ÉÏ»ñÈ¡²»±äUDIDµÄÎÊÌâ¡£²¢¸ø³öÒ»¸ö»ñÈ¡UDIDµÄ¹¤¾ßÀ࣬ʹÓ÷½±ã£¬Ö»ÐèÒªÌæ»»Á½¸öµØ·½¼´¿É¡£
Ò»¡¢iOS²»Óð汾»ñÈ¡UDIDµÄ·½·¨±È½Ï
1£©iOS 5.0
iOS 2.0°æ±¾ÒÔºóUIDeviceÌṩһ¸ö»ñÈ¡É豸Ψһ±êʶ·ûµÄ·½·¨uniqueIdentifier£¬Í¨¹ý¸Ã·½·¨ÎÒÃÇ¿ÉÒÔ»ñÈ¡É豸µÄÐòÁкţ¬Õâ¸öÒ²ÊÇĿǰΪֹΨһ¿ÉÒÔÈ·ÈÏΨһµÄ±êʾ·û¡£ºÃ¾°²»³¤£¬ÒòΪ¸ÃΨһ±êʶ·ûÓëÊÖ»úÒ»Ò»¶ÔÓ¦£¬Æ»¹û¾õµÃ¿ÉÄÜ»áй¶Óû§Òþ˽£¬ËùÒÔÔÚ
iOS 5.0Ö®ºó¸Ã·½·¨¾Í±»·ÏÆúµôÁË¡£
¡¡¡¡¶øÇÒÆ»¹û×öµÄ¸üºÝ£¬½ñÄê5Ô·ÝÒÔºóÌá½»App StoreµÄ²úÆ·¶¼²»ÔÊÐíÔÙÓÃuniqueIdentifier½Ó¿Ú£¬ÉõÖÁÓÐЩÅóÓÑÒòΪ´úÂëÖÐÓÐUDID»¹±»´ò»ØÀ´£¬¿´À´ÕâÌõ·ÊDZ»·âËÀÁË¡£
2£©iOS 6.0
iOS 6.0ϵͳÐÂÔöÁËÁ½¸öÓÃÓÚÌæ»»uniqueIdentifierµÄ½Ó¿Ú£¬·Ö±ðÊÇ£ºidentifierForVendor£¬advertisingIdentifier¡£
identifierForVendor½Ó¿ÚµÄ¹Ù·½Îĵµ½éÉÜÈçÏÂ:
The value of this property is the same
for apps that come from the same vendor running on the
same device. A different value is returned for apps
on the same device that come from different vendors,
and for apps on different devices regardless of vendor.
The value of this property may be nil if the app is
running in the background, before the user has unlocked
the device the first time after the device has been
restarted. If the value is nil, wait and get the value
again later.
The value in this property remains the
same while the app (or another app from the same vendor)
is installed on the iOS device. The value changes when
the user deletes all of that vendor¡¯s apps from the
device and subsequently reinstalls one or more of them.
Therefore, if your app stores the value of this property
anywhere, you should gracefully handle situations where
the identifier changes.
´ó¸ÅÒâ˼¾ÍÊÇ¡°Í¬Ò»¿ª·¢É̵ÄAPPÔÚÖ¸¶¨»úÆ÷É϶¼»á»ñµÃͬһ¸öID¡£µ±ÎÒÃÇɾ³ýÁËijһ¸öÉ豸ÉÏij¸ö¿ª·¢É̵ÄËùÓÐAPPÖ®ºó£¬Ï´λñÈ¡½«»á»ñÈ¡µ½²»Í¬µÄID¡£¡±
Ò²¾ÍÊÇ˵ÎÒÃÇͨ¹ý¸Ã½Ó¿Ú²»ÄÜ»ñÈ¡ÓÃÀ´Î¨Ò»±êʶÉ豸µÄID£¬ÎÊÌâ×ÜÊÇÄѲ»µ¹´ÏÃ÷µÄ³ÌÐòÔ±£¬ÓÚÊÇ´ó¼ÒÏëµ½ÁËʹÓÃWiFiµÄmacµØÖ·À´È¡´úÒѾ·ÏÆúÁ˵ÄuniqueIdentifier·½·¨¡£¾ßÌåµÄ·½·¨ÍíÉÏÓкܶ࣬´ó¼Ò¸ÐÐËȤµÄ¿ÉÒÔ×Ô¼ºÕÒÕÒ£¬Õâ¶ùÌṩһ¸öÍøÖ·:
http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone
3£©iOS 7.0
iOS 7ÖÐÆ»¹ûÔÙÒ»´ÎÎÞÇéµÄ·âɱmacµØÖ·£¬Ê¹ÓÃ֮ǰµÄ·½·¨»ñÈ¡µ½µÄmacµØÖ·È«²¿¶¼±ä³ÉÁË02:00:00:00:00:00¡£ÓÐÎÊÌâ×ܵĽâ¾ö°¡£¬ÓÚÊÇËÄ´¦²é×ÊÁÏ£¬ÖÕÓÚÓÐÁË˼·ÊÇ·ñ¿ÉÒÔʹÓÃKeyChainÀ´±£´æ»ñÈ¡µ½µÄΨһ±êʾ·ûÄØ£¬ÕâÑùÒÔºó¼´Ê¹APPɾÁËÔÙ×°»ØÀ´£¬Ò²¿ÉÒÔ´ÓKeyChainÖжÁÈ¡»ØÀ´¡£ÓÐÁË·½ÏòÒÔºó¾Í¿ªÊ¼×ö£¬¿´¹ØÓÚKeyChainµÄ¹Ù·½Îĵµ£¬¿´¹Ù·½Ê¹ÓÃKeyChainµÄDemo£¬´ó¸Å»¨ÁËÒ»ÏÂÎçʱ¼ä£¬ÎÊÌâÖÕÓÚ½â¾öÁË¡£
¶þ¡¢KeyChain½éÉÜ
ÎÒÃǸãiOS¿ª·¢£¬Ò»¶¨¶¼ÖªµÀOS XÀïÃæµÄKeyChain(Ô¿³×´®)£¬Í¨³£ÒªÏçÕò¼°µ÷ÊԵϰ£¬¶¼µÃ°²×°Ö¤ÊéÖ®ÀàµÄ£¬ÕâЩ֤Êé¾ÍÊDZ£´æÔÚKeyChainÖУ¬»¹ÓÐÎÒÃÇÆ½Ê±ä¯ÀÀÍøÒ³¼Ç¼µÄÕ˺ÅÃÜÂëÒ²¶¼ÊǼǼÔÚKeyChainÖС£iOSÖеÄKeyChainÏà±ÈOS
X±È½Ï¼òµ¥£¬Õû¸öϵͳֻÓÐÒ»¸öKeyChain£¬Ã¿¸ö³ÌÐò¶¼¿ÉÒÔÍùKeyChainÖмǼÊý¾Ý£¬¶øÇÒÖ»ÄܶÁÈ¡µ½×Ô¼º³ÌÐò¼Ç¼ÔÚKeyChainÖеÄÊý¾Ý¡£iOSÖÐSecurity.framework¿ò¼ÜÌṩÁËËĸöÖ÷ÒªµÄ·½·¨À´²Ù×÷KeyChain:
// ²éѯ
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);
// Ìí¼Ó
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result);
// ¸üÐÂKeyChainÖеÄItem
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);
// ɾ³ýKeyChainÖеÄItem
OSStatus SecItemDelete(CFDictionaryRef query) |
ÕâËĸö·½·¨²ÎÊý±È½Ï¸´ÔÓ£¬Ò»µ©´«´í¾Í»áµ¼Ö²Ù×÷KeyChainʧ°Ü£¬Õâ¿é¶ùÎĵµÖнéÉܵıȽÏÏêϸ£¬´ó¼Ò¿ÉÒÔ²é²é¹Ù·½ÎĵµKeychain
Services Reference¡£
Ç°ÃæÌáµ½ÁËÿ¸öAPPÖ»ÔÊÐí·ÃÎÊ×Ô¼ºÔÚKeyChainÖмǼµÄÊý¾Ý£¬ÄÇôÊDz»ÊǾÍûÓбðµÄ°ì·¨·ÃÎÊÆäËûAPP´æÔÚKeyChainµÄÊý¾ÝÁË£¿
Æ»¹ûÌṩÁËÒ»¸ö·½·¨ÔÊÐíͬһ¸ö·¢É̵Ķà¸öAPP·ÃÎʸ÷APPÖ®¼äµÄ;¾¶£¬¼´ÔÚµ÷SecItemAddÌí¼ÓÊý¾ÝµÄʱºòÖ¸¶¨AccessGroup£¬¼´·ÃÎÊ×é¡£Ò»¸öAPP¿ÉÒÔÊôÓÚͬÊÂÊôÓÚ¶à¸ö·Ö×飬Ìí¼ÓKeyChainÊý¾Ý·ÃÎÊ×éÐèÒª×öÒ»ÏÂÁ½¼þÊÂÇé:
a¡¢ÔÚAPP targetµÄbulibSettingÀïÃæÉèÖÃCode
Signing Entitlements£¬Ö¸Ïò°üº¬AceessGroupµÄ·Ö×éÐÅÏ¢µÄplistÎļþ¡£¸ÃÎļþ±ØÐëºÍ¹¤³ÌÎļþÔÚͬһ¸öĿ¼Ï£¬ÎÒÔÚÌí¼Ó·ÃÎÊ·Ö×éµÄʱºò¾ÍÒòΪplistÎļþλÖÃÎÊÌ⣬²Ù×÷KeyChainʧ°Ü£¬²éÕÒÕâ¸öÎÊÌ⻹»¨Á˺þõÄʱ¼ä¡£

b¡¢ÔÚ¹¤³ÌĿ¼ÏÂн¨Ò»¸öKeychainAccessGroups.plistÎļþ£¬¸ÃÎļþµÄ½á¹¹ÖÐ×î¶¥²ãµÄ½Úµã±ØÐëÊÇÒ»¸öÃûΪ¡°keychain-access-groups¡±µÄArray£¬²¢ÇÒ¸ÃArrayÖÐÿһÏî¶¼ÊÇÒ»¸öÃèÊö·Ö×éµÄNSString¡£¶ÔÓÚStringµÄ¸ñʽҲÓÐÏàÓ¦ÒªÇ󣬸ñʽΪ:"AppIdentifier.com.***"£¬ÆäÖÐAPPIdentifier¾ÍÊÇÄãµÄ¿ª·¢ÕßÕʺŶÔÓ¦µÄID¡£
c¡¢ÔÚ´úÂëÖÐÍùKeyChainÖÐAddÊý¾ÝµÄʱºò£¬ÉèÖÃkSecAttrAccessGroup£¬´úÂëÈçÏÂ:
NSString *accessGroup = [NSString stringWithUTF8String:"APPIdentifier.com.cnblogs.smileEvday"];
if (accessGroup != nil)
{
#if TARGET_IPHONE_SIMULATOR
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
#else
[dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
} |
Õâ¶Î´úÂëÊÇ´Ó¹Ù·½µÄDemoÖÐÖ±½Ó¿½±´¹ýÀ´µÄ£¬¸ù¾Ý×¢ÊÍÎÒÃÇ¿ÉÒÔ¿´µ½£¬Ä£ÄâÆ÷ÊDz»Ö§³ÖAccessGroupµÄ£¬ËùÒÔ²ÅÐÐÁËÔ¤±àÒëºêÀ´Ñ¡ÔñÐÔÌí¼Ó¡£
×¢£ºappIdentifer¾ÍÊÇ¿ª·¢ÕßÕʺŵÄÄÇÒ»´®±êʶ£¬ÈçÏÂͼËùʾ£º

´ò¿ªxcodeµÄOrganizer£¬Ñ¡ÔñDeviceÑ¡Ï£¬Á¬½ÓÉ豸¾Í¿ÉÒÔ¿´µ½É豸Éϰ²×°µÄ¿ª·¢ÕßÕ˺ÅÃèÊöÎļþÁÐ±í£¬ÆäÖеÚÎåÁÐ×ʼµÄ10¸ö×Ö·û¼´ÎªApp
Identifier£¬Õâ¿é¶ùÇ°ÃæÐ´µÄ²»ÊǺÜÇå³þ£¬ºÃ¶àÅóÓѼÓÎÒqqÎÊÎÒ£¬½ñÌìÌØµØ²¹ÉÏ¡£
Èý¡¢Ê¹ÓÃKeyChain±£´æºÍ»ñÈ¡UDID
˵ÁËÕâô¶àÖÕÓÚ½øÈëÕýÌâÁË£¬ÈçºÎÔÚiOS 7ÉÏÃæ»ñÈ¡µ½²»±äµÄUDID¡£ÎÒÃǽ«µÚ¶þ²¿·ÖËù½²µÄ֪ʶֱ½ÓÓ¦ÓýøÀ´¾Í¿ÉÒÔÁËÇáËÉ´ïµ½ÎÒÃÇÒªµÄЧ¹ûÁË£¬ÏÂÃæÎÒÃÇÏÈ¿´¿´ÍùÈçºÎ½«»ñÈ¡µ½µÄidentifierForVendorÌí¼Óµ½KeyChainÖеĴúÂë¡£
+ (BOOL)settUDIDToKeyChain:(NSString*)udid
{
NSMutableDictionary *dictForAdd = [[NSMutableDictionary alloc] init];
[dictForAdd setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
[dictForAdd setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:kSecAttrDescription];
[dictForAdd setValue:@"UUID" forKey:(id)kSecAttrGeneric];
// Default attributes for keychain item.
[dictForAdd setObject:@"" forKey:(id)kSecAttrAccount];
[dictForAdd setObject:@"" forKey:(id)kSecAttrLabel];
// The keychain access group attribute determines if this item can be shared
// amongst multiple apps whose code signing entitlements contain the same keychain access group.
NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
if (accessGroup != nil)
{
#if TARGET_IPHONE_SIMULATOR
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
#else
[dictForAdd setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
}
const char *udidStr = [udid UTF8String];
NSData *keyChainItemValue = [NSData dataWithBytes:udidStr length:strlen(udidStr)];
[dictForAdd setValue:keyChainItemValue forKey:(id)kSecValueData];
OSStatus writeErr = noErr;
if ([SvUDIDTools getUDIDFromKeyChain]) { // there is item in keychain
[SvUDIDTools updateUDIDInKeyChain:udid];
[dictForAdd release];
return YES;
}
else { // add item to keychain
writeErr = SecItemAdd((CFDictionaryRef)dictForAdd, NULL);
if (writeErr != errSecSuccess) {
NSLog(@"Add KeyChain Item Error!!! Error Code:%ld", writeErr);
[dictForAdd release];
return NO;
}
else {
NSLog(@"Add KeyChain Item Success!!!");
[dictForAdd release];
return YES;
}
}
[dictForAdd release];
return NO;
} |
ÉÏÃæ´úÂëÖУ¬Ê×Ïȹ¹½¨Ò»¸öÒªÌí¼Óµ½KeyChainÖÐÊý¾ÝµÄDictionary£¬°üº¬Ò»Ð©»ù±¾µÄKeyChain
ItemµÄÊý¾ÝÀàÐÍ£¬ÃèÊö£¬·ÃÎÊ·Ö×éÒÔ¼°×îÖØÒªµÄÊý¾ÝµÈÐÅÏ¢£¬×îºóͨ¹ýµ÷ÓÃSecItemAdd·½·¨½«ÎÒÃÇÐèÒª±£´æµÄUUID±£´æµ½KeyChainÖС£
»ñÈ¡KeyChainÖÐÏàÓ¦Êý¾ÝµÄ´úÂëÈçÏÂ:
+ (NSString*)getUDIDFromKeyChain
{
NSMutableDictionary *dictForQuery = [[NSMutableDictionary alloc] init];
[dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
// set Attr Description for query
[dictForQuery setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]
forKey:kSecAttrDescription];
// set Attr Identity for query
NSData *keychainItemID = [NSData dataWithBytes:kKeychainUDIDItemIdentifier
length:strlen(kKeychainUDIDItemIdentifier)];
[dictForQuery setObject:keychainItemID forKey:(id)kSecAttrGeneric];
// The keychain access group attribute determines if this item can be shared
// amongst multiple apps whose code signing entitlements contain the same keychain access group.
NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
if (accessGroup != nil)
{
#if TARGET_IPHONE_SIMULATOR
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
#else
[dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
}
[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];
[dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
OSStatus queryErr = noErr;
NSData *udidValue = nil;
NSString *udid = nil;
queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, (CFTypeRef*)&udidValue);
NSMutableDictionary *dict = nil;
[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, (CFTypeRef*)&dict);
if (queryErr == errSecItemNotFound) {
NSLog(@"KeyChain Item: %@ not found!!!", [NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]);
}
else if (queryErr != errSecSuccess) {
NSLog(@"KeyChain Item query Error!!! Error code:%ld", queryErr);
}
if (queryErr == errSecSuccess) {
NSLog(@"KeyChain Item: %@", udidValue);
if (udidValue) {
udid = [NSString stringWithUTF8String:udidValue.bytes];
}
}
[dictForQuery release];
return udid;
} |
ÉÏÃæ´úÂëµÄÁ÷³ÌÒ²²î²»¶àÒ»Ñù£¬Ê×ÏÈ´´½¨Ò»¸öDictionary£¬ÆäÖÐÉèÖÃһϲéÕÒÌõ¼þ£¬È»ºóͨ¹ýSecItemCopyMatching·½·¨»ñÈ¡µ½ÎÒÃÇ֮ǰ±£´æµ½KeyChainÖеÄÊý¾Ý¡£
ËÄ¡¢×ܽá
±¾ÎĽéÉÜÁËʹÓÃKeyChainʵÏÖAPPɾ³ýºóÒÀÈ»¿ÉÒÔ»ñÈ¡µ½ÏàͬµÄUDIDÐÅÏ¢µÄ½â¾ö·½·¨¡£
Äã¿ÉÄÜÓÐÒÉÎÊ£¬Èç¹ûϵͳÉý¼¶ÒÔºó£¬ÊÇ·ñÈÔÈ»¿ÉÒÔ»ñÈ¡µ½Ö®Ç°¼Ç¼µÄUDIDÊý¾Ý£¿
´ð°¸Êǿ϶¨µÄ£¬ÕâÒ»µãÎÒרÃÅ×öÁ˲âÊÔ¡£¾ÍËãÎÒÃdzÌÐòɾ³ýµô£¬ÏµÍ³¾¹ýÉý¼¶ÒÔºóÔÙ°²×°»ØÀ´£¬ÒÀ¾É¿ÉÒÔ»ñÈ¡µ½Óë֮ǰһÖµÄUDID¡£µ«Êǵ±ÎÒÃǰÑÕû¸öϵͳ»¹ÔÒÔºóÊÇ·ñ»¹ÄÜ»ñÈ¡µ½Ö®Ç°¼Ç¼µÄUDID£¬ÕâÒ»µãÎÒ¾õµÃÓ¦¸Ã²»ÐУ¬²»¹ýÊÖ»úÀïÃæÊý¾ÝÌ«¶à£¬Ã»ÓвâÊÔ£¬Èç¹û´ó¼ÒÓÐÐËȤ¿ÉÒÔ²âÊÔһϣ¬ÑéÖ¤Ò»ÏÂÎҵIJÂÏë¡£
|