SignalR使用Azure Web角色精彩地扩展。但是,当我在Azure辅助角色中使用自托管OWIN项目时,SignalR将在添加多个实例时开始出现问题。为了记录,我的项目使用Redis作为背板。
将Azure辅助角色实例增加到一个以上时,客户端连接将随机失败,并显示错误" ConnectionId格式错误" 。我相信这是由于负载均衡导致单个客户端的协商跨越多个服务器时引起的;我不相信参与协商的多台服务器可以解密数据(DPAPI在封面下?)。
我尝试设置< machineKey /> app.config中的validationKey和decryptionKey,但这似乎没有什么区别;问题依然存在。同样,该项目将作为Web角色(IIS)正常工作,但不能作为工作者角色(OWIN自托管)。
假设这是DpapiDataProtectionProvider的问题,我如何确保提供程序在多个服务器/实例之间呈现相同的加密/解密结果?
解决方案
SignalR(DpapiDataProtectionProvider)使用的默认保护提供程序似乎不支持Azure Worker Role scaleout。通过滚动我自己的示例提供程序,我能够扩展SignalR / OWIN / Azure Worker并且不接收随机400 HTTP /" ConnectionId的格式不正确"。请注意,以下示例不会保护/保护令牌。
public class ExampleDataProvider : IDataProtector
{
public byte[] Protect(byte[] userData)
{
Trace.TraceInformation("Protect called: " + Convert.ToBase64String(userData));
return userData;
}
public byte[] Unprotect(byte[] protectedData)
{
Trace.TraceInformation("Unprotect called: " + Convert.ToBase64String(protectedData));
return protectedData;
}
}
public class ExampleProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
Trace.TraceInformation("Example Protection Provider Created");
return new ExampleDataProvider();
}
}
在Owin启动期间注入自定义提供程序:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.SetDataProtectionProvider(new ExampleProtectionProvider());
GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration("0.0.0.0", 0, "", "Example"));
app.MapSignalR(new HubConfiguration
{
EnableDetailedErrors = true
});
app.UseWelcomePage("/");
}
}
答案 0 :(得分:5)
SignalR使用来自IAppBuilder.Properties [" security.DataProtectionProvider"]的IDataProtectionProvider,如果它不为空。
在调用MapSignalR之前,可以在Startup.Configuration中用自己的IDataProtectionProvider替换它。
通过提供您自己的IDataProtectionProvider,您可以确保每个工作角色使用相同的密钥来保护/取消保护。