C# 无法从Xamarin iOS SecKeychain检索GUID
在我的Xamarin iOS应用程序中,我将DeviceId和AccessToken存储在密钥链中。对于保存和检索访问令牌,我的代码工作正常,但是对于设备id(它是一个GUID),在保存设备id时,它给出的结果是C# 无法从Xamarin iOS SecKeychain检索GUID,c#,ios,xamarin.ios,C#,Ios,Xamarin.ios,在我的Xamarin iOS应用程序中,我将DeviceId和AccessToken存储在密钥链中。对于保存和检索访问令牌,我的代码工作正常,但是对于设备id(它是一个GUID),在保存设备id时,它给出的结果是DuplicateItem,在检索设备id时,它给出的结果是ItemNotFound。我对设备Id和访问令牌使用单独的密钥。这是我的密码 public const string DEVICE_ID = "DEVICE_ID"; public const string ACCESS_TOK
DuplicateItem
,在检索设备id时,它给出的结果是ItemNotFound
。我对设备Id和访问令牌使用单独的密钥。这是我的密码
public const string DEVICE_ID = "DEVICE_ID";
public const string ACCESS_TOKEN = "ACCESS_TOKEN";
public static string GetValue(string key)
{
var query = new SecRecord(SecKind.GenericPassword)
{
Generic = NSData.FromString(key)
};
SecStatusCode result;
var match = SecKeyChain.QueryAsRecord(query, out result);
if (result == SecStatusCode.Success)
{
return match.ValueData.ToString();
}
return string.Empty;
}
public static void SetValue(string value, string key)
{
var query = new SecRecord(SecKind.GenericPassword)
{
ValueData = NSData.FromString(value),
Generic = NSData.FromString(key)
};
var result = SecKeyChain.Add(query);
}
我通过如下方法调用保存并获取设备id
SetValue(Guid.NewGuid(), DEVICE_ID);
string deviceId = GetValue(DEVICE_ID);
它可能看起来很奇怪,但我不知道它为什么会这样,是否有人遇到过这个问题,或者我的代码中是否有任何错误。请帮帮我。这是我们用来存储和检索SecKeyChain的类,我建议使用我们的类,看看是否得到相同的结果
using Security;
using Foundation;
public class KeyChain
{
public const string DEVICE_ID = "DEVICE_ID";
public const string ACCESS_TOKEN = "ACCESS_TOKEN";
public string ValueForKey(string key)
{
var record = ExistingRecordForKey (key);
SecStatusCode resultCode;
var match = SecKeyChain.QueryAsRecord(record, out resultCode);
if (resultCode == SecStatusCode.Success)
return NSString.FromData (match.ValueData, NSStringEncoding.UTF8);
else
return String.Empty;
}
public void SetValueForKey(string value, string key)
{
var record = ExistingRecordForKey (key);
if (value.IsNullOrEmpty())
{
if (!ValueForKey(key).IsNullOrEmpty())
RemoveRecord(record);
return;
}
// if the key already exists, remove it
if (!ValueForKey(key).IsNullOrEmpty())
RemoveRecord(record);
var result = SecKeyChain.Add(CreateRecordForNewKeyValue(key, value));
if (result != SecStatusCode.Success)
{
throw new Exception(String.Format("Error adding record: {0}", result));
}
}
private SecRecord CreateRecordForNewKeyValue(string key, string value)
{
return new SecRecord(SecKind.GenericPassword)
{
Account = key,
Service = ServiceName,
Label = key,
ValueData = NSData.FromString(value, NSStringEncoding.UTF8),
};
}
private SecRecord ExistingRecordForKey(string key)
{
return new SecRecord(SecKind.GenericPassword)
{
Account = key,
Service = ServiceName,
Label = key,
};
}
private bool RemoveRecord(SecRecord record)
{
var result = SecKeyChain.Remove(record);
if (result != SecStatusCode.Success)
{
throw new Exception(String.Format("Error removing record: {0}", result));
}
return true;
}
}
然后,要从中检索信息的类和/或方法如下所示:
public class OtherClass
{
Public void GetInfo()
{
// Store device id
KeyChain.SetValueForKey(Guid.NewGuid(), KeyChain.DEVICE_ID);
// Retrieve device id
string value = KeyChain.ValueForKey(DEVICE_ID);
// Store access token
KeyChain.SetValueForKey(Guid.NewGuid(), KeyChain.ACCESS_TOKEN);
// Retrie acce token
string value = KeyChain.ValueForKey(ACCESS_TOKEN);
}
}
这是我们用于存储和检索SecKeyChain的类,我建议使用我们的类,看看是否得到相同的结果
using Security;
using Foundation;
public class KeyChain
{
public const string DEVICE_ID = "DEVICE_ID";
public const string ACCESS_TOKEN = "ACCESS_TOKEN";
public string ValueForKey(string key)
{
var record = ExistingRecordForKey (key);
SecStatusCode resultCode;
var match = SecKeyChain.QueryAsRecord(record, out resultCode);
if (resultCode == SecStatusCode.Success)
return NSString.FromData (match.ValueData, NSStringEncoding.UTF8);
else
return String.Empty;
}
public void SetValueForKey(string value, string key)
{
var record = ExistingRecordForKey (key);
if (value.IsNullOrEmpty())
{
if (!ValueForKey(key).IsNullOrEmpty())
RemoveRecord(record);
return;
}
// if the key already exists, remove it
if (!ValueForKey(key).IsNullOrEmpty())
RemoveRecord(record);
var result = SecKeyChain.Add(CreateRecordForNewKeyValue(key, value));
if (result != SecStatusCode.Success)
{
throw new Exception(String.Format("Error adding record: {0}", result));
}
}
private SecRecord CreateRecordForNewKeyValue(string key, string value)
{
return new SecRecord(SecKind.GenericPassword)
{
Account = key,
Service = ServiceName,
Label = key,
ValueData = NSData.FromString(value, NSStringEncoding.UTF8),
};
}
private SecRecord ExistingRecordForKey(string key)
{
return new SecRecord(SecKind.GenericPassword)
{
Account = key,
Service = ServiceName,
Label = key,
};
}
private bool RemoveRecord(SecRecord record)
{
var result = SecKeyChain.Remove(record);
if (result != SecStatusCode.Success)
{
throw new Exception(String.Format("Error removing record: {0}", result));
}
return true;
}
}
然后,要从中检索信息的类和/或方法如下所示:
public class OtherClass
{
Public void GetInfo()
{
// Store device id
KeyChain.SetValueForKey(Guid.NewGuid(), KeyChain.DEVICE_ID);
// Retrieve device id
string value = KeyChain.ValueForKey(DEVICE_ID);
// Store access token
KeyChain.SetValueForKey(Guid.NewGuid(), KeyChain.ACCESS_TOKEN);
// Retrie acce token
string value = KeyChain.ValueForKey(ACCESS_TOKEN);
}
}
我假设您不是每次都使用相同的密钥来存储它?#我使用相同的密钥“deviceid”来存储和检索数据。您不能对GUID和令牌使用相同的密钥。。。否则,当你来取回钥匙链时,钥匙链怎么知道你在请求哪一个。你必须确保你使用的是两个不同的“键”,我使用的是不同的键。很抱歉没有给出详细的代码,我已经更新了我的代码。因此,为了澄清您在存储字符串(GUID等)时所做的操作:SetValue(GUID.NewGuid(),ACCESS_TOKEN);和设置值(Guid.NewGuid(),设备ID)?我假设您不是每次都使用相同的密钥来存储它?#我使用相同的密钥“deviceid”来存储和检索数据。您不能对GUID和令牌使用相同的密钥。。。否则,当你来取回钥匙链时,钥匙链怎么知道你在请求哪一个。你必须确保你使用的是两个不同的“键”,我使用的是不同的键。很抱歉没有给出详细的代码,我已经更新了我的代码。因此,为了澄清您在存储字符串(GUID等)时所做的操作:SetValue(GUID.NewGuid(),ACCESS_TOKEN);和设置值(Guid.NewGuid(),设备ID)?谢谢大家,很好用。你能说说我的代码有什么问题吗?@RikudouSennin我想这只是因为你没有使用'var record=ExistingRecordForKey(key);'并将记录作为查询而不是键传入。多谢各位,它工作得很好。你能说说我的代码有什么问题吗?@RikudouSennin我想这只是因为你没有使用'var record=ExistingRecordForKey(key);'并将记录作为查询而不是键传入。