保存并从钥匙链加载| Swift[重复]

这个问题在这里已经有答案了
通过钥匙链保存和检索价值

(7个答案)

五年前关闭的

如何简单地将字符串存储在Keychain中,并在需要时加载。
有几种SO解决方案主要涉及Git回购。但我需要最新Swift的最小和最简单的解决方案。当然,我不想添加git框架来简单地在我的项目中存储密码

还有类似的解决方案,通过KeyChain保存和检索价值,但对我来说并不适用。厌倦了编译器错误

##最简源##

代码>导入基础
进口担保
//常量标识符
让userAccount="“认证用户”;
让accessGroup="“证券服务”;
/**
*新条目的用户定义键
*注意:为新的安全项添加新密钥,并在加载和保存方法中使用它们
*/
让passwordKey="KeyForPassword"
//密钥链查询的参数
让kSecClassValue=NSString(格式:kSecClass)
让kSecAttrAccountValue=NSString(格式:kSecAttrAccount)
让kSecValueDataValue=NSString(格式:kSecValueData)
让kSecClassGenericPasswordValue=NSString(格式:kSecClassGenericPassword)
让kSecAttrServiceValue=NSString(格式:kSecAttrService)
让kSecMatchLimitValue=NSString(格式:kSecMatchLimit)
让kSecReturnDataValue=NSString(格式:kSecReturnData)
让kSecMatchLimitOneValue=NSString(格式:kSecMatchLimitOne)
公共类KeychainService:NSObject{
/**
*用于执行保存和加载查询的公开方法。
*/
公共类func savePassword(令牌:NSString){
self.save(密码键,数据:令牌)
}
公共类func loadPassword()->NSString{
返回self.load(passwordKey)
}
/**
*用于查询密钥链的内部方法。
*/
私有类func save(服务:NSString,数据:NSString){
让dataFromString:NSData=data.dataUsingEncoding(NSUTF8StringEncoding,allowossyconversion:false)!
//实例化新的默认密钥链查询
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,用户帐户,dataFromString],叉子:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecValueDataValue])
//删除任何现有项目
SecItemDelete(keychainQuery作为CFDictionaryRef)
//添加新的钥匙链项目
SecItemAdd(keychainQuery作为CFDictionaryRef,nil)
}
私有类函数加载(服务:NSString)->NSString{
//实例化新的默认密钥链查询
//告诉查询返回一个结果
//将结果限制为一项
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,用户帐户,kCFBooleanTrue,kSecMatchLimitOneValue],forKeys:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecReturnDataValue,kSecMatchLimitValue])
var dataTypeRef:AnyObject?
//搜索钥匙链项目
let状态:OSStatus=SecItemCopyMatching(keychainQuery和dataTypeRef)
var contentsOfKeychain:NSString?=nil
如果状态==errSecSuccess{
如果让retrievedData=dataTypeRef作为NSData{
contentsOfKeychain=NSString(数据:retrievedData,编码:NSUTF8StringEncoding)
}
}否则{
打印(“未从钥匙链中检索到任何内容。状态代码\(状态)”)
}
返回密钥链的内容
}
}

##呼叫示例##

KeychainService.savePassword("Pa55worD")
让password=KeychainService.loadPassword()//password="Pa55worD"

##SWIFT 4:具有更新和删除密码的版本

导入
进口担保
//看https://stackoverflow.com/a/37539998/1694526
//密钥链查询的参数
让kSecClassValue=NSString(格式:kSecClass)
让kSecAttrAccountValue=NSString(格式:kSecAttrAccount)
让kSecValueDataValue=NSString(格式:kSecValueData)
让kSecClassGenericPasswordValue=NSString(格式:kSecClassGenericPassword)
让kSecAttrServiceValue=NSString(格式:kSecAttrService)
让kSecMatchLimitValue=NSString(格式:kSecMatchLimit)
让kSecReturnDataValue=NSString(格式:kSecReturnData)
让kSecMatchLimitOneValue=NSString(格式:kSecMatchLimitOne)
公共类KeychainService:NSObject{
类func updatePassword(服务:字符串、帐户:字符串、数据:字符串){
如果让dataFromString:Data=Data.Data(使用:String.Encoding.utf8,allowLossyConversion:false){
//实例化新的默认密钥链查询
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,帐户],forKeys:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue])
让status=SecItemUpdate(keychainQuery作为CFDictionary,[kSecValueDataValue:dataFromString]作为CFDictionary)
如果(状态!=errSecSuccess){
如果let err=SecCopyErrorMessageString(状态为nil){
打印(“读取失败:\(错误)”
}
}
}
}
类func removePassword(服务:字符串,帐户:字符串){
//实例化新的默认密钥链查询
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,帐户,kCFBooleanTrue],叉子:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecReturnDataValue])
//删除任何现有项目
让status=SecItemDelete(keychainQuery作为CFDictionary)
如果(状态!=errSecSuccess){
如果let err=SecCopyErrorMessageString(状态为nil){
打印(“删除失败:\(错误)”
}
}
}
类func savePassword(服务:字符串、帐户:字符串、数据:字符串){
如果let dataFromString=data.data(使用:String.Encoding.utf8,allowLossyConversion:false){
//实例化新的默认密钥链查询
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,帐户,dataFromString],叉子:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecValueDataValue])
//添加新的钥匙链项目
让status=SecItemAdd(keychainQuery作为CFDictionary,nil)
如果(status!=errSecSuccess){//始终检查状态
如果let err=SecCopyErrorMessageString(状态为nil){
打印(“写入失败:\(错误)”
}
}
}
}
类func loadPassword(服务:字符串,帐户:字符串)->字符串{
//实例化新的默认密钥链查询
//告诉查询返回一个结果
//将结果限制为一项
let keychainQuery:NSMutableDictionary=NSMutableDictionary(对象:[kSecClassGenericPasswordValue,服务,帐户,kCFBooleanTrue,kSecMatchLimitOneValue],forKeys:[kSecClassValue,kSecAttrServiceValue,kSecAttrAccountValue,kSecReturnDataValue,ksecMatchLimitionValue])
var dataTypeRef:AnyObject?
//搜索钥匙链项目
let状态:OSStatus=SecItemCopyMatching(keychainQuery和dataTypeRef)
var contentsOfKeychain:字符串?
如果状态==errSecSuccess{
如果让retrievedData=dataTypeRef作为数据{
contentsOfKeychain=String(数据:retrievedData,编码:String.encoding.utf8)
}
}否则{
打印(“未从钥匙链中检索到任何内容。状态代码\(状态)”)
}
返回密钥链的内容
}
}

您需要想象以下连接到一个文本输入字段和一个标签,然后连接四个按钮,每个按钮对应一个方法

class ViewController:NSViewController{
@IBOutlet弱var enterPassword:NSTextField!
@IBMOutlet弱var retrievedPassword:NSTextField!
让服务=“myService”;
让账户=“我的账户”;
//只能在以后工作
@iAction func updatePassword(\发送方:任意){
KeychainService.updatePassword(服务:服务,帐户:帐户,数据:enterPassword.stringValue)
}
@iAction func removePassword(\发送方:任意){
KeychainService.removePassword(服务:服务,帐户:帐户)
}
@iAction func密码集(\发送方:任意){
让password=enterPassword.stringValue
KeychainService.savePassword(服务:服务,帐户:帐户,数据:密码)
}
@iAction func密码获取(\发送方:任意){
如果让str=KeychainService.loadPassword(服务:服务,帐户:帐户){
retrievedPassword.stringValue=str
}
else{retrievedPassword.stringValue=“密码不存在”}
}
}

##迅捷的

发表评论