Notice
Recent Posts
Recent Comments
Link
투케이2K
19. (ios/swift) keychain 키 체인 , uuid 사용해 디바이스 고유값 영구 저장 실시 본문
[개발 환경 설정]
개발 툴 : XCODE
개발 언어 : SWIFT
[소스 코드]
import Foundation
import Security
import UIKit
class S_Keychain {
// MARK: [키 체인 클래스 사용 방법]
/*
1. 디바이스 정보 저장 : S_Keychain().createDeviceID() => 리턴 값 true / false
2. 디바이스 정보 조회 : S_Keychain().getDeviceID() => 저장된 디바이스 고유값 문자열
3. 디바이스 정보 삭제 : S_Keychain().deleteDeviceID() => 리턴 값 true / false
*/
// MARK: [키 체인 설명]
/*
1. Keychain 은 디바이스 안에 암호화된 데이터 저장 공간입니다
2. Keychain 은 보안 기능이 뛰어나 사용자 정보 및 결제 정보 등 민감한 정보를 저장할 수 있습니다
3. Keychain 은 앱 종료 및 앱 삭제 후 재설치를 진행해도 동일하게 저장된 값을 사용할 수 있습니다
- 영구적인 데이터
- 사용자가 삭제하지 않는 이상 유지
- Keychain 은 사용자가 데이터를 삭제하거나, 휴대폰 공장 초기화를 진행 시 삭제됩니다
4. 설정 패키지 : import Security
*/
// MARK: [UUID 설명]
/*
1. uuis 는 32개의 문자+숫자로 이루어집니다
2. iOS4까지는 iOS기기의 고유 넘버로 udid를 사용했지만, 보안 문제로 iOS5부터는 uudi(임의로 생성한 고유값)를 사용합니다
3. uuid는 앱을 삭제하면 새롭게 생성됩니다
4. uuid는 Vender 에 따라서 값이 달라집니다 (공급업체(벤더)가 같은 앱들은 모두 같은 고유 ID를 가집니다)
5. uuid 외에도 ADID (IDFA) 라는 것이 있는데 이는 광고 식별자이고 기기마다 고유한 값을 가집니다
- 앱 스토어 등록 심사 시 필수 광고 식별자 사용을 체크하고 사유를 적어야합니다 (아니면, 앱 스토어 등록 거부될 수 있습니다)
6. 설정 패키지 : import UIKit
*/
// MARK: [Keychain 생성 정보 정의]
private let account = "ServiceSaveKey"
private let service = Bundle.main.bundleIdentifier
// MARK: [Keychain 사용해 디바이스 고유값 저장 실시]
func createDeviceID() -> Bool {
guard let service = self.service
else {
print("")
print("[S_Keychain >> createDeviceID() : Service Check : false]")
print("")
return false
}
// 디바이스 고유값 생성 실시
let deviceID = self.setDeviceID()
print("")
print("[S_Keychain >> createDeviceID() : account : \(account)]")
print("[S_Keychain >> createDeviceID() : service : \(service)]")
print("[S_Keychain >> createDeviceID() : deviceID : \(deviceID)]")
print("")
// 키 체인 쿼리 생성
let query:[CFString: Any]=[kSecClass: kSecClassGenericPassword, // 보안 데이터 저장
kSecAttrService: service, // 키 체인에서 해당 앱을 식별하는 값 (앱만의 고유한 값)
kSecAttrAccount: account, // 앱 내에서 데이터를 식별하기 위한 키에 해당하는 값 (사용자 계정)
kSecValueData: deviceID.data(using: .utf8, allowLossyConversion: false)!] // 키값에 디바이스 고유값 저장
// keychain 에 저장을 수행한 결과 값 반환 (true / false)
let status: OSStatus = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print("")
print("[S_Keychain >> createDeviceID() : Success Status : \(status)]")
print("")
return true
}
else {
print("")
print("[S_Keychain >> createDeviceID() : Fail Status : \(status)]")
print("")
return false
}
}
// MARK: [Keychain 사용해 디바이스 고유값 호출 실시]
func getDeviceID() -> String {
guard let service = self.service
else {
print("")
print("[S_Keychain >> getDeviceID() : Service Check : false]")
print("")
return ""
}
print("")
print("[S_Keychain >> getDeviceID() : account : \(account)]")
print("[S_Keychain >> getDeviceID() : service : \(service)]")
print("")
// 키 체인 쿼리 정의
let query:[CFString: Any]=[kSecClass: kSecClassGenericPassword, // 보안 데이터 저장
kSecAttrService: service, // 키 체인에서 해당 앱을 식별하는 값 (앱만의 고유한 값)
kSecAttrAccount : account, // 앱 내에서 데이터를 식별하기 위한 키에 해당하는 값 (사용자 계정)
kSecReturnData : true, // kSecReturnData에 true를 리턴시켜 값을 불러옵니다
kSecReturnAttributes: true, // kSecReturnAttributes에 true를 리턴시켜 값을 불러옵니다
kSecMatchLimit : kSecMatchLimitOne] // 값이 일치하는 것을 찾습니다
// 키 체인에 저장된 값을 읽어옵니다
var dataTypeRef : CFTypeRef?
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
// 처리 결과가 성공인 경우 >> 키 체인에서 읽어온 값을 Data 타입으로 변환 >> 다시 String 타입으로 변환
if status == errSecSuccess {
guard let existingItem = dataTypeRef as? [String: Any]
else {
print("")
print("[S_Keychain >> getDeviceID() : Type Check : false]")
print("")
return ""
}
let deviceData = existingItem[kSecValueData as String] as? Data
let uuidData = String(data: deviceData!, encoding: .utf8)!
print("")
print("[S_Keychain >> getDeviceID() : Success Status : \(status)]")
print("")
return uuidData
}
else if status == errSecItemNotFound || status == -25300 {
print("")
print("[S_Keychain >> getDeviceID() : Fail Status : 저장된 데이터가 없습니다]")
print("")
return ""
}
else {
// 처리결과가 실패라면 nil을 반환
print("")
print("[S_Keychain >> getDeviceID() : Fail Status : \(status)]")
print("")
return ""
}
}
// MARK: [Keychain 에 저장된 값 삭제 수행]
func deleteDeviceID() -> Bool {
guard let service = self.service
else {
print("")
print("[S_Keychain >> deleteDeviceID() : Service Check : false]")
print("")
return false
}
print("")
print("[S_Keychain >> deleteDeviceID() : account : \(account)]")
print("[S_Keychain >> deleteDeviceID() : service : \(service)]")
print("")
// 키 체인 쿼리 정의
let query:[CFString: Any]=[kSecClass: kSecClassGenericPassword, // 보안 데이터 저장
kSecAttrService: service, // 키 체인에서 해당 앱을 식별하는 값 (앱만의 고유한 값)
kSecAttrAccount : account] // 앱 내에서 데이터를 식별하기 위한 키에 해당하는 값 (사용자 계정)
// 현재 저장되어 있는 값 삭제
let status: OSStatus = SecItemDelete(query as CFDictionary)
if status == errSecSuccess {
print("")
print("[S_Keychain >> deleteDeviceID() : Success Status : \(status)]")
print("")
return true
}
else {
print("")
print("[S_Keychain >> deleteDeviceID() : Fail Status : \(status)]")
print("")
return false
}
}
// MARK: [디바이스 고유 값 추출 메소드]
func setDeviceID() -> String {
return UIDevice.current.identifierForVendor!.uuidString
}
}
[결과 출력]
반응형
'IOS' 카테고리의 다른 글
21. (ios/swift) 앱 빌드 정보 확인 실시 - Bundle.main.infoDictionary (0) | 2021.10.23 |
---|---|
20. (ios/swift) Package Manager 패키지 매니저 사용해 라이브러리 추가 방법 설명 - xcode 11 버전 (0) | 2021.10.23 |
18. (ios/swift) 프리퍼런스 preference 반영구적 데이터 저장 실시 - UserDefaults (0) | 2021.10.23 |
17. (ios/swift) url scheme 스키마 데이터 전송 및 받은 데이터 확인 (0) | 2021.10.22 |
16. (ios/swift) 외부 앱 실행 및 앱 스토어 이동 실시 - 스키마 scheme (0) | 2021.10.21 |
Comments