将令牌本地存储在Xamarin.IOS中

时间:2018-08-08 11:27:20

标签: xamarin.ios

我正在研究Xamarin跨平台的本机项目,我必须同时存储令牌(登录后从服务器获取)和Android和IOS端。在Android方面,我使用了SharedPreferences,效果很好,但找不到IOS的解决方案。现在我正在使用KeyChain,但结果总是错误的。

这是我的代码:

KeyChain类:

using System;
using Foundation;
using Security;

namespace BloodNotes.iOS
{
    public class KeyChain
    {
        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 == "")
            {
                if (ValueForKey(key) != "")
                    RemoveRecord(record);

                return;
            }

            // if the key already exists, remove it
            if (ValueForKey(key) != "")
                RemoveRecord(record);

            var result = SecKeyChain.Add(CreateRecordForNewKeyValue(key, value));
            if (result != SecStatusCode.Success)
            {
                throw new Exception(String.Format("Error adding record: " + result));  // I ALWAYS GET THIS EXCEPTION
            }
        }

        private SecRecord CreateRecordForNewKeyValue(string key, string value)
        {
            return new SecRecord(SecKind.GenericPassword)
            {
                Account = key,
                ValueData = NSData.FromString(value, NSStringEncoding.UTF8),
            };
        }

        private SecRecord ExistingRecordForKey(string key)
        {
            return new SecRecord(SecKind.GenericPassword)
            {
                Account = key,
                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;
        }
    }
}

和TokenService:

using BloodNotes.ViewModel;
using Foundation;
using System.Diagnostics;

namespace BloodNotes.iOS.TokenService
{
    class TokenService : Service.ITokenService
    {
        public const string KEY = "token";

        public void SaveToken(string token)
        {
            KeyChain storage = new KeyChain();
            storage.SetValueForKey(token, KEY);

            Debug.WriteLine("RESULT: " + storage.ValueForKey(KEY));
        } 
    }
}

请给我建议。

提前感谢您的回答!

1 个答案:

答案 0 :(得分:0)

最后,我找到了解决方案。使用NSUserDefaults.StandardUserDefaults代替KeyChain,所以我的TokenService如下:

using Foundation;
using System.Diagnostics;

namespace BloodNotes.iOS.TokenService
{
    class TokenService : Service.ITokenService
    {
        public const string KEY = "token";

        public void SaveToken(string token)
        {
            var storage = NSUserDefaults.StandardUserDefaults;
            NSString value = new NSString(token);
            NSString key = new NSString(KEY);
            storage.SetValueForKey(value, key);

            Debug.WriteLine("RESULT: " + storage.ValueForKey(key).ToString());
        } 
    }
}