首页 > 解决方案 > 在 Xamarin.IOS 中本地存储令牌

问题描述

我正在开发一个 Xamarin 跨平台本机项目,我必须在 Android 和 IOS 端存储令牌(登录后从服务器获取)。在 Android 方面,我使用了 SharedPreferences,效果很好,但我找不到 IOS 的解决方案。现在我在使用 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;
        }
    }
}

和令牌服务:

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

请给我建议。

提前感谢您的回答!

标签: xamarin.ios

解决方案


最后,我找到了解决方案。而不是 KeyChain 使用 NSUserDefaults.StandardUserDefaults,所以我的 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());
        } 
    }
}

推荐阅读