首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Xamarin.iOS密钥链在试图查询存储NSData的密钥时挂起

Xamarin.iOS密钥链在试图查询存储NSData的密钥时挂起
EN

Stack Overflow用户
提问于 2018-11-27 22:36:28
回答 2查看 260关注 0票数 0

我有一个现有的企业部署应用程序,它使用OpenID Connect进行身份验证。通过身份验证后,为了安全起见,我将AuthState对象存储在iOS密钥链中,并能够在以后使用Face/Touch ID对用户进行签名(考虑到AuthState中的刷新令牌仍然有效)。AuthState对象如下所示:

代码语言:javascript
复制
namespace OpenId.AppAuth
{
    [Register ("OIDAuthState", true)]
    public class AuthState : NSObject, INSCoding, INativeObject, IDisposable, INSSecureCoding
    {
        [CompilerGenerated]
        private static readonly IntPtr class_ptr = Class.GetHandle ("OIDAuthState");

        [CompilerGenerated]
        private object __mt_ErrorDelegate_var;

        [CompilerGenerated]
        private object __mt_StateChangeDelegate_var;

        public override IntPtr ClassHandle {
            get;
        }

        [CompilerGenerated]
        public virtual NSError AuthorizationError {
            [Export ("authorizationError")]
            get;
        }

        [CompilerGenerated]
        public virtual IAuthStateErrorDelegate ErrorDelegate {
            [Export ("errorDelegate", ArgumentSemantic.Weak)]
            get;
            [Export ("setErrorDelegate:", ArgumentSemantic.Weak)]
            set;
        }

        [CompilerGenerated]
        public virtual bool IsAuthorized {
            [Export ("isAuthorized")]
            get;
        }

        [CompilerGenerated]
        public virtual AuthorizationResponse LastAuthorizationResponse {
            [Export ("lastAuthorizationResponse")]
            get;
        }

        [CompilerGenerated]
        public virtual RegistrationResponse LastRegistrationResponse {
            [Export ("lastRegistrationResponse")]
            get;
        }

        [CompilerGenerated]
        public virtual TokenResponse LastTokenResponse {
            [Export ("lastTokenResponse")]
            get;
        }

        [CompilerGenerated]
        public virtual string RefreshToken {
            [Export ("refreshToken")]
            get;
        }

        [CompilerGenerated]
        public virtual string Scope {
            [Export ("scope")]
            get;
        }

        [CompilerGenerated]
        public virtual IAuthStateChangeDelegate StateChangeDelegate {
            [Export ("stateChangeDelegate", ArgumentSemantic.Weak)]
            get;
            [Export ("setStateChangeDelegate:", ArgumentSemantic.Weak)]
            set;
        }

        public static IAuthorizationFlowSession PresentAuthorizationRequest (AuthorizationRequest authorizationRequest, UIViewController presentingViewController, AuthStateAuthorizationCallback callback);

        [CompilerGenerated]
        [DesignatedInitializer]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        [Export ("initWithCoder:")]
        public AuthState (NSCoder coder)
            : base (NSObjectFlag.Empty);

        [CompilerGenerated]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected AuthState (NSObjectFlag t)
            : base (t);

        [CompilerGenerated]
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected internal AuthState (IntPtr handle)
            : base (handle);

        [Export ("initWithAuthorizationResponse:")]
        [CompilerGenerated]
        public AuthState (AuthorizationResponse authorizationResponse)
            : base (NSObjectFlag.Empty);

        [Export ("initWithAuthorizationResponse:tokenResponse:")]
        [CompilerGenerated]
        public AuthState (AuthorizationResponse authorizationResponse, TokenResponse tokenResponse)
            : base (NSObjectFlag.Empty);

        [Export ("initWithRegistrationResponse:")]
        [CompilerGenerated]
        public AuthState (RegistrationResponse registrationResponse)
            : base (NSObjectFlag.Empty);

        [Export ("initWithAuthorizationResponse:tokenResponse:registrationResponse:")]
        [DesignatedInitializer]
        [CompilerGenerated]
        public AuthState (AuthorizationResponse authorizationResponse, TokenResponse tokenResponse, RegistrationResponse registrationResponse)
            : base (NSObjectFlag.Empty);

        [Export ("encodeWithCoder:")]
        [CompilerGenerated]
        [Preserve (Conditional = true)]
        public virtual void EncodeTo (NSCoder encoder);

        [Export ("performActionWithFreshTokens:")]
        [CompilerGenerated]
        public unsafe virtual void PerformWithFreshTokens ([BlockProxy (typeof(ObjCRuntime.Trampolines.NIDAuthStateAction))] AuthStateAction action);

        [Export ("performActionWithFreshTokens:additionalRefreshParameters:")]
        [CompilerGenerated]
        public unsafe virtual void PerformWithFreshTokens ([BlockProxy (typeof(ObjCRuntime.Trampolines.NIDAuthStateAction))] AuthStateAction action, NSDictionary<NSString, NSString> additionalParameters);

        [Export ("authStateByPresentingAuthorizationRequest:UICoordinator:callback:")]
        [CompilerGenerated]
        public unsafe static IAuthorizationFlowSession PresentAuthorizationRequest (AuthorizationRequest authorizationRequest, IAuthorizationUICoordinator UICoordinator, [BlockProxy (typeof(ObjCRuntime.Trampolines.NIDAuthStateAuthorizationCallback))] AuthStateAuthorizationCallback callback);

        [Export ("setNeedsTokenRefresh")]
        [CompilerGenerated]
        public virtual void SetNeedsTokenRefresh ();

        [Export ("tokenRefreshRequest")]
        [CompilerGenerated]
        public virtual TokenRequest TokenRefreshRequest ();

        [Export ("tokenRefreshRequestWithAdditionalParameters:")]
        [CompilerGenerated]
        public virtual TokenRequest TokenRefreshRequest (NSDictionary<NSString, NSString> additionalParameters);

        [Export ("updateWithAuthorizationResponse:error:")]
        [CompilerGenerated]
        public virtual void Update (AuthorizationResponse authorizationResponse, NSError error);

        [Export ("updateWithTokenResponse:error:")]
        [CompilerGenerated]
        public virtual void Update (TokenResponse tokenResponse, NSError error);

        [Export ("updateWithAuthorizationError:")]
        [CompilerGenerated]
        public virtual void Update (NSError authorizationError);

        [Export ("updateWithRegistrationResponse:")]
        [CompilerGenerated]
        public virtual void UpdateWithRegistrationResponse (RegistrationResponse registrationResponse);

        [CompilerGenerated]
        protected override void Dispose (bool disposing);
    }
}

iOS 12.1更新之前,一切都很好

问题:安装ios 12.1更新后的,只有在以发布模式运行(在连接到VS for Mac调试器时以开发模式进行调试时工作)查询密钥链中存储此AuthState对象的二进制NSData表示形式的现有密钥时,才会挂起该应用程序,最终该应用程序因响应时间超过10秒而终止

有人遇到过类似的问题吗?如果有人能揭示这里可能发生的事情,或者指出我的正确方向,那将是令人惊奇的。

其他信息:

如何获得NSData二进制表示AppAuth对象:

代码语言:javascript
复制
NSData authStateData = NSKeyedArchiver.ArchivedDataWithRootObject(authState);

如何将这个NSData保存到密钥链中:

代码语言:javascript
复制
    var secAccess = new SecAccessControl(SecAccessible.WhenUnlockedThisDeviceOnly, SecAccessControlCreateFlags.UserPresence);
    var secRecord = new SecRecord(SecKind.GenericPassword)
    {
        Account = "keystring",
        Service = "ServiceNameString",
        Label = "keystring",
        ValueData = authStateData,
        AccessControl = secAccess
    };
    var result = SecKeyChain.Add(secRecord);

如何查询keychain中的现有数据

代码语言:javascript
复制
var searchRecord = new SecRecord(SecKind.GenericPassword)
{
    Service = ServiceName,
    Label = key,
};
var match = SecKeyChain.QueryAsRecord(searchRecord, out SecStatusCode resultCode);

我检查了一下,设备日志中没有明显的错误。我错过了iOS 12.1中的一个变化,它对此有很大影响吗?

更新:我重构了代码,使其只在密钥链中存储加密密钥密码,而不是存储整个AuthState对象,并将加密的序列化AuthState存储到本地文件中。仍然可以看到相同的问题,在设备上的调试模式中,所有操作、写入和从密钥链的读取都很好,当没有在同一设备上附加调试器的情况下运行时,相同的构建、写入,当成功验证TouchID/FaceID后读取挂起时,Xamarin.iOS SDK中是否有一个bug没有赶上最新的iOS中引起这一问题的一些变化?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-30 16:44:42

我已经解决了我的问题,这似乎是某种种族条件锁定了应用程序,因为调用保存到关键链是在主线程上完成的。通常情况下,这个调用是非常快速的,并且在过去锁定任何东西都没有问题,但是iOS 12.1更新中的一些东西改变了这一点。无论如何,我只是显式地运行代码,将加密密码保存到后台线程中的密钥链中,解决了这个问题:

代码语言:javascript
复制
Task.Run(() =>
{
    var keychain = new KeyChain();
    keychain.SetValueForKey("securedvalue", "securedvaluekey");
}).ConfigureAwait(false);
票数 0
EN

Stack Overflow用户

发布于 2018-11-29 05:37:20

您应该启用密钥链共享权限。

在Entitlements.plist中

这是一个你可以参考的similar case

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53509301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档