키체인을 사용 할 일이있어 블러그를 검색해서 약간의 수정해서 Wrapper Class로 작성했다.
// Created by DongOh Lim on 2023/04/18.
// 참고사이트 : https://developerbee.tistory.com/56
import Foundation
import Security
class KeyChainWrapper: NSObject {
/*
* 외부로 제공되는 메소드
* serviceIdentifier: 키체인에서 해당 앱을 식별하는 값으로 앱만의 고유한 값을 써야합니다. (데이터를 해당 앱에서만 사용하기 위해)
* userAccount: 앱 내에서 데이터를 식별하기 위한 키에 해당하는 값입니다.
*/
public class func saveData(serviceIdentifier:NSString, userAccount:NSString, data: String) {
self.save(service: serviceIdentifier, userAccount: userAccount, data: data)
}
public class func loadData(serviceIdentifier:NSString, userAccount:NSString) -> String? {
let data = self.load(service: serviceIdentifier, userAccount: userAccount)
return data
}
public class func updateData(serviceIdentifier:NSString, userAccount:NSString, data: String) {
self.update(service: serviceIdentifier, userAccount: userAccount, data: data)
}
public class func dataDelete(serviceIdentifier:NSString, userAccount:NSString) {
self.delete(service: serviceIdentifier, userAccount: userAccount)
}
/*
* Keychain 에 실제 접근하는 내부 메소드
*/
private class func save(service: NSString, userAccount:NSString, data: String) {
let dataFromString: Data = data.data(using: String.Encoding.utf8)!
// Instantiate a new default keychain query
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String,
kSecAttrService as String: service,
kSecAttrAccount as String: userAccount,
kSecValueData as String: dataFromString]
// Delete any existing items
SecItemDelete(query as CFDictionary)
// Add the new keychain item
SecItemAdd(query as CFDictionary, nil)
}
private class func load(service: NSString, userAccount:NSString) -> String? {
// Instantiate a new default keychain query
// Tell the query to return a result
// Limit our results to one item
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String,
kSecAttrService as String: service,
kSecAttrAccount as String: userAccount,
kSecReturnData as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitOne as String]
var retrievedData: NSData?
var dataTypeRef:AnyObject?
var contentsOfKeychain: String?
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
if (status == errSecSuccess) {
retrievedData = dataTypeRef as? NSData
contentsOfKeychain = String(data: retrievedData! as Data, encoding: String.Encoding.utf8)
}
else
{
print("Nothing was retrieved from the keychain. Status code \(status)")
contentsOfKeychain = nil
}
return contentsOfKeychain
}
private class func update(service: NSString, userAccount: NSString, data: String) {
let dataFromString: Data = data.data(using: String.Encoding.utf8)!
let previousQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String,
kSecAttrService as String: service,
kSecAttrAccount as String: userAccount]
let updateQuery: [CFString: Any] = [kSecValueData: dataFromString]
let status = SecItemUpdate(previousQuery as CFDictionary, updateQuery as CFDictionary)
if status == errSecSuccess {
print("update complete")
} else {
print("not finished update")
}
}
private class func delete(service: NSString, userAccount: NSString) {
let deleteQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword as String,
kSecAttrService as String: service,
kSecAttrAccount as String: userAccount]
let status = SecItemDelete(deleteQuery as CFDictionary)
if status == errSecSuccess {
print("remove key-data complete")
} else {
print("remove key-data failed")
}
}
}
사용방법
// 디바이스 UUID 키체인 체크 및 저장 예제
let bundleID = appBundleID() as? NSString ?? "번들아이디"
let deviceUUID = KeyChainWrapper.loadData(serviceIdentifier: bundleID, userAccount: "uuid")
if deviceUUID != nil {
log(direction: .ETC, ofType: self, datas: "UUID : \(String(describing: deviceUUID))")
uuid = deviceUUID!
} else {
if let device_uuid = UIDevice.deviceUUID {
log(direction: .ETC, ofType: self, datas: "UUID : \(String(describing: device_uuid))")
KeyChainWrapper.saveData(serviceIdentifier: bundleID, userAccount: "uuid", data: device_uuid)
} else {
log(direction: .ERROR, ofType: self, datas: "UUID NULL")
}
}
'Swift > 기타' 카테고리의 다른 글
[SWIFT]스토어 앱 업데이트 체크 StoreUpdateCheckWrapper (0) | 2023.05.16 |
---|---|
[SWIFT]App 애니메이션 효과 강제종료 (1) | 2023.05.09 |
[SWIFT]XCode 14.3 Archive시 PhaseScriptExecution 오류 (0) | 2023.04.27 |
[SWIFT]스크린 캡쳐 및 녹화 감지 (0) | 2023.04.26 |
[SWIFT]Contraints 코드로 활성화 비활성화 제어하기 (0) | 2023.04.24 |