c# - 使用 RedisSessionStateProvider 时出现 Microsoft.Owin.Security.AuthenticationTicket SerializationException

标签 c# redis owin openid-connect session-state-provider

我在我的应用程序中使用 Owin OpenIdConnectAuthentication 模块,并尝试将我的 session 状态移动到 Redis。为此,我正在使用 Microsoft.Web.Redis.RedisSessionStateProvider。当我更新我的 web.config 以添加 RedisSessionStateProvider 时,我开始收到此错误:

Type 'Microsoft.Owin.Security.AuthenticationTicket' in Assembly 'Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.

堆栈跟踪

[SerializationException: Type 'Microsoft.Owin.Security.AuthenticationTicket' in Assembly 'Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.]
   System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) +10951483
   System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) +230
   System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() +121
   System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +182
   System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +51
   System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +540
   System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +131
   System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) +12
   Microsoft.Web.Redis.RedisUtility.GetBytesFromObject(Object data) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\Shared\RedisUtility.cs:65
   Microsoft.Web.Redis.RedisUtility.AppendUpdatedOrNewItemsInList(ChangeTrackingSessionStateItemCollection sessionItems, List`1 list) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\Shared\RedisUtility.cs:37
   Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateIfLockIdMatchPrepare(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout, String[]& keyArgs, Object[]& valueArgs) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisConnectionWrapper.cs:323
   Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateAndReleaseLockIfLockIdMatch(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisConnectionWrapper.cs:350
   Microsoft.Web.Redis.RedisSessionStateProvider.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisSessionStateProvider.cs:408
   System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +565
   System.Web.SessionState.SessionStateModule.OnEndRequest(Object source, EventArgs eventArgs) +139
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69 

我是不是在某处遗漏了一些配置?我能找到的关于序列化 AuthenticationTicket 对象的所有文档都是针对 OAuth server 实现的。

最佳答案

我们使用的是 AspNetAuthSessionStore sample来自武士刀。显然,此示例仅适用于 InProc session 状态。我们通过手动序列化 AuthenticationTicket 进行了以下更改以解决此问题:

    public Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        string key = Guid.NewGuid().ToString();
        HttpContext httpContext = HttpContext.Current;
        CheckSessionAvailable(httpContext);
        //httpContext.Session[key + ".Ticket"] = ticket;       // Remove
        var ticketSerializer = new TicketSerializer();         // Add
        var ticketBytes = ticketSerializer.Serialize(ticket);  // Add
        httpContext.Session[key + ".Ticket"] = ticketBytes;    // Add

        return Task.FromResult(key);
    }

关于c# - 使用 RedisSessionStateProvider 时出现 Microsoft.Owin.Security.AuthenticationTicket SerializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33575637/

相关文章:

session-variables - OWIN 自主机中等效的 session 变量

c# - 如何使用 "dynamic"变量从匿名类型读取属性

c# - 从c#读取文件需要时提示UAC

c# - 你能有一个没有线程的 TCP 客户端吗

RedisBloom : Option to add items (bit strings) as is with no hashing?

ruby-on-rails - 在 rails 中使用 resque 调度程序时如何检查作业的状态?

c# - Microsoft.Owin 2.0.2.0 安装 3.0.0.0 后依赖冲突

c# - 如何编写异常处理的自动化测试

java - 使用 spring boot 设置 Redis sentinel

c# - NancyFx - Razor 编译错误