더 이상 사용되지 않는 UIDevice uniqueIdentifier-지금 무엇을해야합니까?


501

UIDevice uniqueIdentifier 속성은 iOS 5 에서 더 이상 사용되지 않으며 iOS 7 이상 에서는 사용할 수 없다는 사실 밝혀 졌습니다. 다른 방법이나 속성을 사용할 수 없거나 앞으로 나올 것으로 보이지 않습니다.

기존의 많은 앱은 특정 장치를 고유하게 식별하기 위해이 속성에 밀접하게 의존합니다. 앞으로이 문제를 어떻게 처리 할 수 ​​있습니까?

2011-2012문서에서 제안한 내용 은 다음과 같습니다.

특별 고려 사항

uniqueIdentifier 속성을 사용하지 마십시오. 앱에 고유 한 식별자 CFUUIDCreate를 만들려면 함수를 호출하여 를 만들고 클래스를 UUID사용하여 기본 데이터베이스에 쓸 수 NSUserDefaults있습니다.

그러나 사용자가 앱을 제거했다가 다시 설치하는 경우이 값은 동일하지 않습니다.


1
여전히 uniqueIdentifier를 사용하는 앱의 경우 iOS7에서 FFFFFFFF + identifierForVendor를 반환하여 잘못 작성되지 않은 비정기 구독 앱을 많이 위반합니다.
리듬 피스트 맨

좋게도

@CalinChitu 사용자가 푸시 알림을 수락하지 않아도 해당 사용자에 대한 pushID가 계속 발생합니까?
체이스 로버츠

답변:


272

사용자가 앱을 제거했다가 다시 설치하는 경우에 의해 생성 된 UUID CFUUIDCreate 고유합니다. 매번 새 UI를 얻게됩니다.

그러나 고유 하지 않을 수도 있습니다 . 즉, 사용자가 앱을 제거했다가 다시 설치할 때 동일하게 유지되어야합니다. 가장 안정적인 장치 별 식별자는 MAC 주소 인 것으로 보이므로 약간의 노력이 필요합니다. MAC을 쿼리하여 UUID로 사용할 수 있습니다 .

편집 : 물론 항상 동일한 인터페이스의 MAC을 쿼리해야합니다. 가장 좋은 방법은입니다 en0. 인터페이스에 IP가 없거나 작동 중지 된 경우에도 MAC은 항상 존재합니다.

편집 2 : 다른 사람들이 지적했듯이 iOS 6 이후 선호되는 솔루션은 -[UIDevice identifierForVendor] 입니다. 대부분의 경우 이전 버전의 드롭 인 대체품으로 사용할 수 있습니다 -[UIDevice uniqueIdentifier](그러나 앱을 처음 시작할 때 생성되는 UUID는 Apple이 사용하기를 원하는 것입니다).

편집 3 : 이 주요 요점은 주석 잡음에서 길을 잃지 않습니다. MAC 을 UUID로 사용하지 말고 MAC 을 사용하여 해시를 만드십시오 . 해시가 동일한 방식으로 수행되는 경우 다시 설치 및 앱에서도 해시가 항상 동일한 결과를 생성합니다. 어쨌든 요즘 (2013) iOS <6.0에서 "안정된"장치 식별자가 필요한 경우를 제외하고는 더 이상 필요하지 않습니다.

편집 4 : iOS 7에서 Apple은 MAC을 쿼리 할 때 항상 고정 값을 반환하여 MAC을 ID 체계의 기초 로 구체적으로 방해합니다 . 따라서 실제로 -[UIDevice identifierForVendor]를 사용 하거나 설치마다 UUID를 작성해야합니다.


8
사용자가 Wi-Fi를 통해 연결되어 있는지 여부에 따라 mac 주소가 변경되지 않습니까?
Oliver Pearmain

1
@DarkDust : 그러나 wifi에서 셀 모뎀으로 전환하면 활성 인터페이스가 변경되므로 활성 인터페이스의 MAC 주소도 변경되어야합니다. MAC을 얻기 위해 항상 특정 인터페이스를 선택하지 않는 한
user102008

3
@Roger Nolan : 다른 사람의 답변을 수정하지 말고 원저자가 작성한 것처럼 보이는 내용을 추가하십시오. 감사.
DarkDust

2
@RogerNolan 게시물이 커뮤니티 답변이 아닌 한, 수정 사항은 실수를 수정하기위한 것이며 새로운 것을 추가하기위한 것이 아닙니다. 특권을 얻은 이유가 있습니다. 내가 당신의 답변을 편집하고 BS를 작성한다고 상상해보십시오. 사람들은 당신이 그것을 썼을 것이라고 생각할 것입니다. 나는 당신이 그것을 좋아하는지 의심합니다 :-) 그러나 당신은 편집이 일어났다는 알림 받지 못합니다 .
DarkDust

3
Apple은 이제 해시 MAC을 사용하는 앱을 거부합니다.
Idan

91

UDID이미 Apple의 대안을 사용할 수 있습니다 . Kind guy gekitz는 장치 mac-address 및 번들 식별자 UIDeviceUDID기반으로 일종의 카테고리를 생성하는 카테고리를 작성했습니다 .

github에서 코드를 찾을 수 있습니다


3
이 구현은 Apple의 uniqueId와 같이 재설치 과정에서 장치에 대해 고유 한 (MAC 주소) 고유하지만 개인 정보도 존중하며 응용 프로그램에 대해서도 고유합니다 (bundleId도 사용) ... Apple이 API에 포함시켜야한다는 점은 분명합니다. .. 어떤 대안도 더 이상 사용되지 않습니다.
Vincent Guerci

8
그것은 광고 조항, yuck와 함께 이전 스타일의 bsd 라이센스를 사용하지만.
jbtule

8
이제이 게시물을 찾는 다른 사람을 위해 위의 주석 이후 jbtule에 의해 라이센스가 변경되었습니다.
James

1
이 커밋 의견에서 논의 된 바와 같이, 라이브러리는있는 그대로 심각한 프라이버시 유출 문제가 발생하여 사용해서는 안됩니다.
Will

15
iOS 7부터 시스템 02:00:00:00:00:00은 모든 장치에서 MAC 주소를 요청할 때 항상 값을 반환합니다 . 여기를 확인하십시오 : developer.apple.com/library/prerelease/ios/releasenotes/General/…
Hejazi

61

@moonlight가 제안한 링크를 기반으로 여러 테스트를 수행했으며 최상의 솔루션 인 것 같습니다. @DarkDust가 말했듯이 메소드 en0는 항상 사용 가능한 것을 확인 합니다. (MAC + CFBundleIdentifier의 MD5 ) 와 ( MAC의 MD5)
두 가지 옵션이 있습니다. 이들은 항상 같은 값을 반환합니다. 내가 한 테스트 아래 (실제 장치로) :
uniqueDeviceIdentifier
uniqueGlobalDeviceIdentifier

#import "UIDevice+IdentifierAddition.h"

NSLog(@"%@",[[UIDevice currentDevice] uniqueDeviceIdentifier]);
NSLog(@"%@",[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]);

XXXX21f1f19edff198e2a2356bf4XXXX-(WIFI) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX-(WIFI) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX-(3G) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX-(3G) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX-(GPRS) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX-(GPRS) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX-(AirPlane 모드) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX-(AirPlane 모드) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX-앱 제거 및 설치 후 앱 XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi) 제거 및 재설치 후 (Wi-Fi)

유용하기를 바랍니다.

편집 :
다른 사람들이 지적했듯이 iOS 7 의이 솔루션 uniqueIdentifier은 더 이상 사용할 수 없으므로 MAC 주소를 쿼리하면 항상 02 : 00 : 00 : 00 : 00 : 00을 반환합니다.


13
iOS7에에이 실 거예요 작품은, 애플은 MAC 주소의 사용을 제거합니다.
Sarim Sidd

@SarimSidd 현재 iOS 7에 관한 정보는 NDA하에 있으며 여기서 논의 할 수 없습니다.
Mat

57

이것 좀 봐,

우리는 대신 키 체인을 사용할 수 있습니다 NSUserDefaults저장하려면, 클래스 UUID에 의해 생성 CFUUIDCreate.

이런 식으로 우리는 UUID재설치 로 인한 레크리에이션을 피할 수 UUID있으며 동일한 응용 프로그램에서 사용자 제거 및 다시 설치조차 항상 동일한 것을 얻을 수 있습니다.

UUID 사용자가 기기를 재설정 할 때만 다시 생성됩니다.

SFHFKeychainUtils 로이 방법을 시도했지만 매력처럼 작동합니다.


33
이 방법은 UDID를 대체합니다. 또한 장치 형식 (예 : 장치가 소유자를 변경하는 경우)에 따라 식별자를 다시 작성하는 이점이 있습니다. 그러나 사용자가 백업을 암호화하면 키 체인을 다른 장치로 복원 할 수 있습니다. 여러 장치가 동일한 UUID를 공유하는 상황이 발생할 수 있습니다. 이를 피하려면 키 체인 항목의 접근성을로 설정하십시오 kSecAttrAccessibleAlwaysThisDeviceOnly. 이렇게하면 UUID가 다른 장치로 마이그레이션되지 않습니다. 다른 앱에서 UUID에 액세스하려면 kSecAttrAccessGroup키를 사용하십시오 .
Jeevan Takhar

UUID를 키 체인에 저장하는 데 정확히 어느 키를 사용해야합니까?
lostintranslation 18

죄송합니다! 링크가 끊어짐
COVID19

48

자신 만의 UUID를 만든 다음 키 체인에 저장하십시오. 따라서 앱이 제거 되어도 지속됩니다. 대부분의 경우 사용자가 장치간에 마이그레이션하더라도 (예 : 전체 백업 및 다른 장치로 복원) 지속됩니다.

실제로는 사용자 가 관심을 갖는 한 고유 한 사용자 식별자가 됩니다. ( 기기 식별자 보다 낫습니다 ).

예:

UUIDas 를 만들기위한 사용자 정의 방법을 정의하고 있습니다.

- (NSString *)createNewUUID 
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

그런 다음 KEYCHAIN앱을 처음 시작할 때 저장할 수 있습니다 . 따라서 처음 시작한 후 키 체인에서 간단히 사용할 수 있으므로 다시 생성 할 필요가 없습니다. 키 체인을 사용하여 저장하는 주된 이유는 다음과 같습니다. 키 체인을 설정 UUID하면 사용자가 앱을 완전히 제거한 후 다시 설치하더라도 키 체인이 유지됩니다. . 따라서 이것은 영구적으로 저장하는 방식이므로 키가 완전히 고유합니다.

     #import "SSKeychain.h"
     #import <Security/Security.h>

applictaion 발사에 다음 코드를 포함 :

 // getting the unique key (if present ) from keychain , assuming "your app identifier" as a key
       NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];
      if (retrieveuuid == nil) { // if this is the first time app lunching , create key for device
        NSString *uuid  = [self createNewUUID];
// save newly created key to Keychain
        [SSKeychain setPassword:uuid forService:@"your app identifier" account:@"user"];
// this is the one time process
}

sskeychain에서 SSKeychain.m 및 .h 파일을 다운로드하고 SSKeychain.m 및 .h 파일을 프로젝트 로 드래그하고 "Security.framework"를 프로젝트에 추가하십시오. 나중에 UUID를 사용하려면 다음을 사용하십시오.

NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];

identifierForVendor가 작동하지 않기 때문에 완벽하지 않습니다. 어떤 경우에는 nil 또는 0x0을 반환 할 수 있습니다. 이 방법은 완벽하게 작동하는 것 같습니다
CReaTuS

3
제거 / 재설치주기 + 확인 된 애플 앱 제출 후 iOS7에서 작동하는지 확인한 사람이 있습니까?
mindbomb

이 솔루션을 사용하기 시작했습니다. 2 개의 장치 (재 구축, 재설치, 장치 종료)에 대한 여러 테스트에서 id가 동일하다는 것을 보여주었습니다. 아이폰 OS 10.3.
deko

16

아마도 당신은 사용할 수 있습니다 :

[UIDevice currentDevice].identifierForVendor.UUIDString

다음과 같이 애플의 문서는 identifierForVender을 설명합니다 :

이 속성의 값은 동일한 장치에서 실행되는 동일한 공급 업체에서 온 앱의 경우와 동일합니다. 다른 공급 업체에서 제공하는 동일한 장치의 앱과 공급 업체에 관계없이 다른 장치의 앱에 대해 다른 값이 반환됩니다.


호기심 왜 아무도 최근까지이 문제를 제기하지 ... 그리고 지금은 아이폰 OS 6의 새로운 기능을 참조
제임스 Boutcher

1
사용자가 iOS를 업데이트하거나 새 iOS를 설치하면 identifierForVendor의 값이 변경되거나 동일하게 유지됩니까?
Sunil Zalavadiya

1
동일한 공급 업체에서 모든 앱을 제거한 후이 값이 변경됩니다.
Mitesh Khatri

14

OpenUDID더 이상 사용되지 않는에 대한 드롭 인 대체를 사용 하는 것이 UDID좋습니다.

기본적으로와 일치하려면 UDID다음 기능이 필요합니다.

  1. 독특하거나 충분히 독특함 (낮은 확률의 충돌이 허용 될 수 있음)
  2. 재부팅, 복원, 제거를 통한 지속성
  3. 여러 공급 업체의 앱에서 사용 가능 (CPI 네트워크를 통해 사용자를 확보하는 데 유용)-

OpenUDID 위의 사항을 충족하며 나중에 고려할 수 있도록 기본 제공 옵트 아웃 메커니즘이 있습니다.

해당 GitHub를 가리키는 http://OpenUDID.org를 확인 하십시오 . 도움이 되었기를 바랍니다!

부수적으로, 나는 MAC 주소 대안에서 멀어 질 것입니다. MAC 주소는 유혹적이고 보편적 인 해결책처럼 보이지만이 낮은 매달린 과일은 중독되어 있어야합니다. MAC 주소는 매우 중요하며 "이 응용 프로그램 제출"이라고 말하기 전에 Apple이이 응용 프로그램에 대한 액세스를 상당히 사용하지 않을 수 있습니다. MAC 네트워크 주소는 개인 LAN (WLAN) 또는 기타 가상 개인의 특정 장치를 인증하는 데 사용됩니다. 네트워크 (VPN). .. 그것은 이전 UDID보다 훨씬 더 민감합니다!


이것이 어떻게 작동하는지 궁금합니다. 코드는 Objective-C로 작성되었지만 위의 요구 사항에 맞는 다른 좋은 솔루션이 없으므로이 프레임 워크가 다른 이유는 무엇입니까? 이 프레임 워크가 사용하는 솔루션은 여기에 제안 된 답변으로 게시 할 수 있어야합니다.
jake_hetfield

동의합니다. MAC 주소는 대부분 수동으로 구성 할 수 있지만 ( "복제 된"), 대부분은 그렇지 않습니다. UDID에서 D에 항의해야합니다. 이것은 장치 ID가 아니며 UUID (Universally Unique Identifier)입니다. 장치 ID는 Apple의 공장 출하시 ROM의 각 장치에 찍혀 있습니다.
Jay Imerman

물론 무슨 일이 실제로 장치를 고유하게 식별하는 데 필요한 않는 한 iOS7에 대한 최적의 솔루션
이씨를 dharankar

1
OpenUDID는 사용되지 않으며 사용하지 않는 것이 좋습니다
mkll

11

애플은 이런 변화로 많은 사람들을 괴롭혔다. iOS 용 부기 앱 을 개발하고 다른 기기에서 변경 한 내용을 동기화하는 온라인 서비스가 있습니다. 이 서비스는 모든 장치와 그들에게 전파해야하는 변화의 데이터베이스를 유지 관리합니다. 따라서 어떤 장치가 어떤 장치인지 알아야합니다. UIDevice uniqueIdentifier를 사용하여 장치를 추적하고 있으며 가치가있는 것에 대한 생각은 다음과 같습니다.

  • UUID를 생성하고 사용자 기본값으로 저장 하시겠습니까? 사용자가 앱을 삭제할 때 지속되지 않기 때문에 좋지 않습니다. 나중에 다시 설치하면 온라인 서비스가 새 장치 레코드를 작성하지 않아야합니다. 그러면 서버의 자원이 낭비되고 동일한 장치를 두 번 이상 포함하는 장치 목록이 제공됩니다. 사용자가 앱을 다시 설치하면 "Bob 's iPhone"이 둘 이상 표시됩니다.

  • UUID를 생성하고 키 체인에 저장 하시겠습니까? 앱을 제거해도 지속되기 때문에 이것은 나의 계획이었습니다. 그러나 iTunes 백업을 새로운 iOS 장비로 복원 할 때 백업이 암호화되면 키 체인이 전송됩니다. 이전 장치와 새 장치가 모두 서비스중인 경우 동일한 장치 ID를 포함하는 두 개의 장치로 이어질 수 있습니다. 장치 이름이 동일하더라도 온라인 서비스에서 두 장치로 나열되어야합니다.

  • 해시 MAC 주소와 번들 ID를 생성 하시겠습니까? 이것은 내가 필요한 것에 가장 적합한 솔루션처럼 보입니다. 번들 ID로 해싱하면 생성 된 장치 ID가 장치간에 장치를 추적 할 수 없으며 앱 + 장치 조합에 대한 고유 ID를 얻습니다.

Apple의 자체 문서는 시스템 MAC 주소의 해시와 번들 ID 및 버전을 계산하여 Mac App Store 영수증의 유효성을 검사 하는 것에 관한 것입니다. 따라서 아직 알지 못하는 앱 검토를 통과하는지 여부는 정책에 따라 허용되는 것 같습니다.


10
두 번째 요점에 설명 된 상황을 피하려면 키 체인 항목의 접근성을로 설정하십시오 kSecAttrAccessibleAlwaysThisDeviceOnly. 이렇게하면 백업이 암호화 된 경우에도 UUID가 다른 장치로 복원되지 않습니다.
Jeevan Takhar

이것은 실제로 여러 번 본 행동입니다. 예를 들어, iPhone을 Google Sync에 등록합니다. 그런 다음 새 iPhone을 가져 와서 등록하고 voila-동기화 설정에 2 개의 iPhone이 나열됩니다.
Jay Imerman

11

iOS 6의 경우 Apple 에서 NSUUID 클래스 를 사용 하는 것이 좋습니다 .

속성 에 대한 UIDevice 문서 의 메시지에서 다음을 수행하십시오 uniqueIdentifier.

iOS 5.0에서 사용되지 않습니다. 이 클래스의 identifierForVendor 특성 또는 ASIdentifierManager 클래스의 AdvertisingIdentifier 특성을 대신 사용하거나 NSUUID 클래스의 UUID 메소드를 사용하여 UUID를 작성하고이를 사용자 기본 데이터베이스에 쓰십시오.


10

도움이 될 수 있습니다 : 아래 코드를 사용하면 장치를 지우는 것을 제외하고 항상 고유합니다.

UIDevice *myDevice=[UIDevice currentDevice];
NSString *UUID = [[myDevice identifierForVendor] UUIDString];

1
이 코드를 사용했습니다. 그러나 앱을 삭제하고 다시 설치하면 새로운 ID를 얻었습니다
Durgaprasad

1
강력한 방법이 필요하지 않은 경우 간단한 솔루션입니다. 지금 내 앱에서 사용하고 있습니다.
Reuben L.

@Durgaprasad : 벤더에 따라 항상 변경됩니다. 예를 들면 다음과 같습니다. 1. bundleidenedifier : com.abcd.com =>으로 앱을 설치하면 변경됩니다. 2. bundleidenedifier를 사용하여 두 개의 응용 프로그램을 설치 한 경우 : com.abcd.com => 그러면 응용 프로그램이 변경되지 않습니다 (애플 동안 하나의 응용 프로그램 유지)
Ashvin Ajadiya

7

또한 이 오픈 소스 라이브러리uniqueIdentifier 로 변경하는 것이 좋습니다. UDID 교체로 사용할 수있는 응용 프로그램에 고유 ID를 생성하는 응용 프로그램 번들 식별자와 함께 장치의 MAC 주소를 사용 (정말이 개 간단한 분류).

UDID와 달리이 숫자는 모든 앱마다 다릅니다.

포함 NSStringUIDevice카테고리 를 가져 와서 다음과 [[UIDevice currentDevice] uniqueDeviceIdentifier]같이 호출 하면됩니다.

#import "UIDevice+IdentifierAddition.h"
#import "NSString+MD5Addition.h"
NSString *iosFiveUDID = [[UIDevice currentDevice] uniqueDeviceIdentifier]

Github에서 찾을 수 있습니다 :

iOS 5 용 UniqueIdentifier가있는 UIDevice


범주는 다음과 같습니다 (.m 파일 만-헤더의 github 프로젝트 확인).

UIDevice + IdentifierAddition.m

#import "UIDevice+IdentifierAddition.h"
#import "NSString+MD5Addition.h"

#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

@interface UIDevice(Private)

- (NSString *) macaddress;

@end

@implementation UIDevice (IdentifierAddition)

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Private Methods

// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (NSString *) macaddress{
    
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;
    
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }
    
    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return NULL;
    }
    
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);
    
    return outstring;
}

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Public Methods

- (NSString *) uniqueDeviceIdentifier{
    NSString *macaddress = [[UIDevice currentDevice] macaddress];
    NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];  
    NSString *stringToHash = [NSString stringWithFormat:@"%@%@",macaddress,bundleIdentifier];
    NSString *uniqueIdentifier = [stringToHash stringFromMD5];  
    return uniqueIdentifier;
}

- (NSString *) uniqueGlobalDeviceIdentifier{
    NSString *macaddress = [[UIDevice currentDevice] macaddress];
    NSString *uniqueIdentifier = [macaddress stringFromMD5];    
    return uniqueIdentifier;
}

@end

NSString + MD5Addition.m :

#import "NSString+MD5Addition.h"
#import <CommonCrypto/CommonDigest.h>

@implementation NSString(MD5Addition)

- (NSString *) stringFromMD5{
    
    if(self == nil || [self length] == 0)
        return nil;
    
    const char *value = [self UTF8String];
    
    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5(value, strlen(value), outputBuffer);
    
    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }
    return [outputString autorelease];
}

@end

3
iOS 7부터 Apple은 MAC 주소에 대한 상수 값을 반환합니다. 완벽하게 이해됩니다. MAC 주소는 민감합니다.
Roberto


4

MAC 주소를 스푸핑하면 이러한 접근 방식을 사용하여 특정 사용자에게 콘텐츠를 연결하거나 블랙리스트와 같은 보안 기능을 구현할 수 없습니다.

몇 가지 추가 연구를 한 결과, 현재로서는 적절한 대안이없는 것으로 보입니다. 나는 애플이 그들의 결정을 재고하기를 진심으로 바란다.

아마도이 주제에 대해 Apple에게 전자 메일을 보내거나 버그 / 기능 요청을 제출하는 것이 좋습니다. 아마도 개발자에게 전체적인 결과를 알지 못하기 때문일 것입니다.


13
그러나 유효한 점은 UUID가 탈옥 된 전화기에서 스푸핑 / 스위 즐링 될 수 있다고 생각하기 때문에 기술적으로 기존의 [UIDevice uniqueIdentifier]도 결함이 있습니다.
Oliver Pearmain

3
항상 서버에서 식별자를 만들어 장치에 저장할 수 있습니다. 이것이 대부분의 응용 프로그램이 수행하는 방식입니다. iOS 프로그래머에게 특별한 무언가가 필요한 이유를 이해하지 못합니다.
Sulthan

1
@Sulthan은 iOS에서 작동하지 않습니다. 앱을 제거하면 모든 데이터가 사라져서 고유 한 장치 식별자를 보장 할 수있는 방법이 없기 때문입니다.
lkraider

4
키 체인에 저장하면 아닙니다. 어쨌든, 나는 이것이 문제가 된 앱을 본 적이 없다. 앱과 데이터가 삭제 된 경우 동일한 기기 식별자가 필요하지 않습니다. 사용자를 식별하려면 이메일을 요청하십시오.
Sulthan

Apple은 iOS의 새로운 릴리스에서 MAC 주소 액세스가 금지되었습니다.
Ans

4

UIDevice identifierForVendor iOS 6에 도입 된 것은 귀하의 목적에 적합합니다.

identifierForVendor앱 공급 업체에서 기기를 고유하게 식별하는 영숫자 문자열입니다. (읽기 전용)

@property(nonatomic, readonly, retain) NSUUID *identifierForVendor

이 속성의 값은 동일한 장치에서 실행되는 동일한 공급 업체에서 온 앱의 경우와 동일합니다. 다른 공급 업체에서 제공하는 동일한 장치의 앱과 공급 업체와 관련된 다른 장치의 앱에 대해 다른 값이 반환됩니다.

iOS 6.0 이상에서 사용 가능하며 UIDevice.h

iOS 5의 경우이 링크를 참조하십시오. UIDevice-with-UniqueIdentifier-for-iOS-5


4

위에서 언급 한 SSKeychain 및 코드 사용 복사 / 붙여 넣기 (SSKeychain 모듈 추가) 코드는 다음과 같습니다.

+(NSString *) getUUID {

//Use the bundle name as the App identifier. No need to get the localized version.

NSString *Appname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];    

//Check if we have UUID already

NSString *retrieveuuid = [SSKeychain passwordForService:Appname account:@"user"];

if (retrieveuuid == NULL)
{

    //Create new key for this app/device

    CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);

    retrieveuuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);

    CFRelease(newUniqueId);

    //Save key to Keychain
    [SSKeychain setPassword:retrieveuuid forService:Appname account:@"user"];
}

return retrieveuuid;

}


3

다음 코드는 UDID를 얻는 데 도움이됩니다.

        udid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        NSLog(@"UDID : %@", udid);

3

이것은 iOS 5와 iOS 6, 7 모두의 ID를 얻는 데 사용하는 코드입니다.

- (NSString *) advertisingIdentifier
{
    if (!NSClassFromString(@"ASIdentifierManager")) {
        SEL selector = NSSelectorFromString(@"uniqueIdentifier");
        if ([[UIDevice currentDevice] respondsToSelector:selector]) {
            return [[UIDevice currentDevice] performSelector:selector];
        }
    }
    return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}

컴파일러 경고에 대해 무엇을합니까 PerformSelector may cause a leak because its selector is unknown?
Basil Bourque

Apple은이를 거부하기 때문에 더 이상 AdvertisingIdentifier를이 목적으로 사용할 수 없습니다. 더 많은 정보 : techcrunch.com/2014/02/03/...
codeplasma


2

iOS 11은 DeviceCheck 프레임 워크를 도입했습니다. 장치를 고유하게 식별하기위한 완벽한 솔루션이 있습니다.


1

UDID를 얻는 효과적인 방법 :

  1. 두 페이지로 앱 내에서 웹 서버를 시작하십시오. 하나는 특수하게 조작 된 MobileConfiguration 프로파일을 리턴하고 다른 하나는 UDID를 수집해야합니다. 여기 , 여기여기에 더 많은 정보가 있습니다 .
  2. 앱 내부에서 Mobile Safari의 첫 페이지를 열면 설정 프로파일 설치를 요청하는 Settings.app로 리디렉션됩니다. 프로파일을 설치하면 UDID가 두 번째 웹 페이지로 전송되며 앱 내부에서 액세스 할 수 있습니다. (Settings.app에는 필요한 모든 권한과 다른 샌드 박스 규칙이 있습니다).

RoutingHTTPServer 를 사용하는 예 :

import UIKit
import RoutingHTTPServer

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var bgTask = UIBackgroundTaskInvalid
    let server = HTTPServer()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        application.openURL(NSURL(string: "http://localhost:55555")!)
        return true
    }

    func applicationDidEnterBackground(application: UIApplication) {
        bgTask = application.beginBackgroundTaskWithExpirationHandler() {
            dispatch_async(dispatch_get_main_queue()) {[unowned self] in
                application.endBackgroundTask(self.bgTask)
                self.bgTask = UIBackgroundTaskInvalid
            }
        }
    }
}

class HTTPServer: RoutingHTTPServer {
    override init() {
        super.init()
        setPort(55555)
        handleMethod("GET", withPath: "/") {
            $1.setHeader("Content-Type", value: "application/x-apple-aspen-config")
            $1.respondWithData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("udid", ofType: "mobileconfig")!)!)
        }
        handleMethod("POST", withPath: "/") {
            let raw = NSString(data:$0.body(), encoding:NSISOLatin1StringEncoding) as! String
            let plistString = raw.substringWithRange(Range(start: raw.rangeOfString("<?xml")!.startIndex,end: raw.rangeOfString("</plist>")!.endIndex))
            let plist = NSPropertyListSerialization.propertyListWithData(plistString.dataUsingEncoding(NSISOLatin1StringEncoding)!, options: .allZeros, format: nil, error: nil) as! [String:String]

            let udid = plist["UDID"]! 
            println(udid) // Here is your UDID!

            $1.statusCode = 200
            $1.respondWithString("see https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html")
        }
        start(nil)
    }
}

내용은 다음과 같습니다 udid.mobileconfig.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>PayloadContent</key>
        <dict>
            <key>URL</key>
            <string>http://localhost:55555</string>
            <key>DeviceAttributes</key>
            <array>
                <string>IMEI</string>
                <string>UDID</string>
                <string>PRODUCT</string>
                <string>VERSION</string>
                <string>SERIAL</string>
            </array>
        </dict>
        <key>PayloadOrganization</key>
        <string>udid</string>
        <key>PayloadDisplayName</key>
        <string>Get Your UDID</string>
        <key>PayloadVersion</key>
        <integer>1</integer>
        <key>PayloadUUID</key>
        <string>9CF421B3-9853-9999-BC8A-982CBD3C907C</string>
        <key>PayloadIdentifier</key>
        <string>udid</string>
        <key>PayloadDescription</key>
        <string>Install this temporary profile to find and display your current device's UDID. It is automatically removed from device right after you get your UDID.</string>
        <key>PayloadType</key>
        <string>Profile Service</string>
    </dict>
</plist>

프로파일 설치가 실패하지만 (예상 응답을 구현하지 않아도 설명서를 참조하십시오 ) 앱에 올바른 UDID가 표시됩니다. 또한 mobileconfig에 서명 해야합니다 .


1

Swift 3.0의 경우 아래 코드를 사용하십시오.

let deviceIdentifier: String = (UIDevice.current.identifierForVendor?.uuidString)!
NSLog("output is : %@", deviceIdentifier)

1
iOS 11은 DeviceCheck 프레임 워크를 도입했습니다. 장치를 고유하게 식별하기위한 완벽한 솔루션이 있습니다.
Santosh Botre 2012 년

1

당신이 사용할 수있는

NSString *sID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

모든 응용 프로그램에서 장치에 고유합니다.



0

대안을 찾을 때 누군가 가이 질문에 걸려 넘어지면. 나는이 접근법을 IDManager수업 에서 따랐습니다. 이것은 다른 솔루션의 모음입니다. KeyChainUtil은 키 체인에서 읽을 수있는 래퍼입니다. 또한 hashed MAC address일종의 고유 ID로 사용할 수도 있습니다 .

/*  Apple confirmed this bug in their system in response to a Technical Support Incident 
    request. They said that identifierForVendor and advertisingIdentifier sometimes 
    returning all zeros can be seen both in development builds and apps downloaded over the 
    air from the App Store. They have no work around and can't say when the problem will be fixed. */
#define kBuggyASIID             @"00000000-0000-0000-0000-000000000000"

+ (NSString *) getUniqueID {
    if (NSClassFromString(@"ASIdentifierManager")) {
        NSString * asiID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
        if ([asiID compare:kBuggyASIID] == NSOrderedSame) {
            NSLog(@"Error: This device return buggy advertisingIdentifier.");
            return [IDManager getUniqueUUID];
        } else {
            return asiID;
        }

    } else {
        return [IDManager getUniqueUUID];
    }
}


+ (NSString *) getUniqueUUID {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:kBuyassUser andServiceName:kIdOgBetilngService error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager GetUUID];
        uuid = [Util md5String:uuid];
        [KeychainUtils storeUsername:USER_NAME andPassword:uuid forServiceName:SERVICE_NAME updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error getting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

/* NSUUID is after iOS 6. */
+ (NSString *)GetUUID
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

#pragma mark - MAC address
// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Last fallback for unique identifier
+ (NSString *) getMACAddress
{
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if ((buf = malloc(len)) == NULL) {
        printf("Error: Memory allocation error\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2\n");
        free(buf); // Thanks, Remy "Psy" Demerest
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];

    free(buf);
    return outstring;
}

+ (NSString *) getHashedMACAddress
{
    NSString * mac = [IDManager getMACAddress];
    return [Util md5String:mac];
}

+ (NSString *)md5String:(NSString *)plainText
{
    if(plainText == nil || [plainText length] == 0)
        return nil;

    const char *value = [plainText UTF8String];
    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5(value, strlen(value), outputBuffer);

    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }
    NSString * retString = [NSString stringWithString:outputString];
    [outputString release];
    return retString;
}

0
+ (NSString *) getUniqueUUID {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:kBuyassUser andServiceName:kIdOgBetilngService error:&error];
    if (error) {
    NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
    return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager GetUUID];
        uuid = [Util md5String:uuid];
        [KeychainUtils storeUsername:USER_NAME andPassword:uuid forServiceName:SERVICE_NAME updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error getting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

0

ios7에 identifierForVendor 를 사용할 수 있습니다 .

-(NSString*)uniqueIDForDevice
{
    NSString* uniqueIdentifier = nil;
    if( [UIDevice instancesRespondToSelector:@selector(identifierForVendor)] ) { // >=iOS 7
        uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    } else { //<=iOS6, Use UDID of Device       
            CFUUIDRef uuid = CFUUIDCreate(NULL);
            //uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
            uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
            CFRelease(uuid);
         }
    }
return uniqueIdentifier;
}

--중요 사항 ---

UDID와 identifierForVendor가 다릅니다 : ---

1.) On uninstalling  and reinstalling the app identifierForVendor will change.

2.) The value of identifierForVendor remains the same for all the apps installed from the same vendor on the device.

3.) The value of identifierForVendor also changes for all the apps if any of the app (from same vendor) is reinstalled.

확실해 ? ios7에 identifierForVendor를 사용할 수 있습니까?
Avis

0

Apple은 iOS 7부터 모든 공개 API에서 UDID를 숨겼습니다. FFFF로 시작하는 모든 UDID는 가짜 ID입니다. 이전에 작동했던 "UDID 보내기"앱을 더 이상 테스트 장치의 UDID를 수집하는 데 사용할 수 없습니다. (한숨!)

UDID는 기기가 XCode (주최자)에 연결되어있을 때와 기기가 iTunes에 연결되어있을 때 표시됩니다 ( '일련 번호'를 클릭해야 식별자가 표시됩니다).

장비가 프로비저닝 프로파일에 추가하기 위해 UDID를 가져와야하고 XCode에서 직접 수행 할 수없는 경우 iTunes에서 복사 / 붙여 넣기 단계를 수행해야합니다.

PC / Mac에서 iTunes를 사용하지 않고 UDID를 얻는 방법이 있습니까 (iOS 7 릴리스)?


0

나도 문제가 있었고 해결책은 간단합니다.

    // Get Bundle Info for Remote Registration (handy if you have more than one app)
    NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];


    // Get the users Device Model, Display Name, Unique ID, Token & Version Number
    UIDevice *dev = [UIDevice currentDevice];
    NSString *deviceUuid=[dev.identifierForVendor  UUIDString];

    NSString *deviceName = dev.name;

0

완벽하지는 않지만 UDID에 대한 가장 좋고 가장 가까운 대안 중 하나입니다 (iOS 8.1 및 Xcode 6.1을 사용하는 Swift에서).

임의의 UUID 생성

let strUUID: String = NSUUID().UUIDString

그리고 KeychainWrapper 라이브러리를 사용하십시오 :

키 체인에 문자열 값을 추가하십시오.

let saveSuccessful: Bool = KeychainWrapper.setString("Some String", forKey: "myKey")

키 체인에서 문자열 값을 검색하십시오.

let retrievedString: String? = KeychainWrapper.stringForKey("myKey")

키 체인에서 문자열 값을 제거하십시오.

let removeSuccessful: Bool = KeychainWrapper.removeObjectForKey("myKey")

이 솔루션은 키 체인을 사용하므로 앱을 제거한 후 다시 설치 한 후에도 키 체인에 저장된 레코드가 유지됩니다. 이 레코드를 삭제하는 유일한 방법은 장치의 모든 내용과 설정을 재설정하는 것입니다. 그렇기 때문에이 대체 솔루션이 완벽하지는 않지만 Swift를 사용하는 iOS 8.1에서 UDID를 대체하는 최상의 솔루션 중 하나를 유지합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.