2017-07-21 20 views
0

在我的Xamarin iOS應用程序中,我將DeviceId和AccessToken存儲在鑰匙串中。爲了保存和檢索訪問令牌,我的代碼工作正常,但是對於保存設備ID的設備ID(它是一個GUID),它給出了結果DuplicateItem,並且在檢索設備ID時它給出了結果ItemNotFound。我正在使用設備ID和訪問令牌的單獨密鑰。這裏是我的代碼無法從Xamarin iOS中檢索GUID SecKeychain

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); 

它可能看起來很奇怪,但我不知道爲什麼它的行爲就像這樣,沒有任何人有遇到過這個問題或者我的代碼中是否有任何錯誤。請幫幫我。

+0

我假設你沒有使用相同的密鑰,每次來存放它# – Digitalsa1nt

+0

我正在使用相同的密鑰「deviceid」來存儲和檢索數據 – RikudouSennin

+0

以及你不能使用相同的密鑰既GUID和令牌...否則鑰匙串如何知道你要求你哪一個來檢索它們。您必須確保您使用兩個不同的'鑰匙' – Digitalsa1nt

回答

2

這是我們從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); 
    } 
} 
+1

非常感謝,它工作正常。你能說我的代碼有什麼問題嗎? – RikudouSennin

+0

@RududouSennin我認爲這只是因爲你沒有使用'var record = ExistingRecordForKey(key);'並將該記錄作爲查詢而不是密鑰傳遞。 – Digitalsa1nt