生成重置密码令牌在Azure网站中不起作用

我正在使用ASP.NET 5附带的内置UserManager类在我的网站上实现重置密码function。

一切工作正常在我的开发环境。 但是,一旦我在作为Azure网站运行的生产站点中尝试它,我会得到以下exception:

System.Security.Cryptography.CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating. 

这是我如何设置UserManager实例:

 var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider(SiteConfig.SiteName); UserManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<User>(provider.Create(ResetPasswordPurpose)); 

然后,我这样生成令牌(通过电子邮件发送给用户,以便他们可以validation他们确实想要重置密码):

 string token = UserManager.GeneratePasswordResetToken(user.Id); 

不幸的是,当它运行在Azure上时,我得到上面的exception。

我search了一下,发现了这个可能的解决scheme 。 然而,它并没有工作,我仍然得到相同的例外。

根据这个链接,这个会话令牌与Azure等networking农场不兼容。

DpapiDataProtectionProvider利用DPAPI在Web农场/云环境中无法正常工作,因为encryption数据只能由encryption的数据encryption的机器解密。 您需要的是一种对数据进行encryption的方式,以便您的环境中的任何机器都能解密数据。 不幸的是,ASP.NET Identity 2.0不包括除DpapiDataProtectionProvider以外的任何其他IProtectionProvider实现。 不过,推出自己的产品并不难。

一种select是使用MachineKey类 ,如下所示:

 public class MachineKeyProtectionProvider : IDataProtectionProvider { public IDataProtector Create(params string[] purposes) { return new MachineKeyDataProtector(purposes); } } public class MachineKeyDataProtector : IDataProtector { private readonly string[] _purposes; public MachineKeyDataProtector(string[] purposes) { _purposes = purposes; } public byte[] Protect(byte[] userData) { return MachineKey.Protect(userData, _purposes); } public byte[] Unprotect(byte[] protectedData) { return MachineKey.Unprotect(protectedData, _purposes); } } 

为了使用这个选项,你需要遵循几个步骤。

步骤1

修改您的代码以使用MachineKeyProtectionProvider。

 using Microsoft.AspNet.Identity.Owin; // ... var provider = new MachineKeyProtectionProvider(); UserManager.UserTokenProvider = new DataProtectorTokenProvider<User>( provider.Create("ResetPasswordPurpose")); 

第2步

在Web场/云环境中的所有计算机上同步MachineKey值。 这听起来很可怕,但是为了使ViewStatevalidation在Web场中正常工作(它也使用DPAPI),我们已经执行了无数次相同的步骤。

考虑使用IAppBuilder.GetDataProtectionProvider()而不是声明一个新的DpapiDataProtectionProvider

与你类似,我通过从我find的代码示例中configuration我的UserManager来引入此问题:

 public class UserManager : UserManager<ApplicationUser> { public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext())) { // this does not work on azure!!! var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ASP.NET IDENTITY"); this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation")) { TokenLifespan = TimeSpan.FromHours(24), }; } } 

与上面链接的CodePlex问题实际上引用了一个已经更新了一个更简单的问题解决scheme的博客文章 。 它build议保存一个静态引用到IDataProtector

 public partial class Startup { internal static IDataProtectionProvider DataProtectionProvider { get; private set; } public void ConfigureAuth(IAppBuilder app) { DataProtectionProvider = app.GetDataProtectionProvider(); // other stuff. } } 

…然后从UserManager内引用它

 public class UserManager : UserManager<ApplicationUser> { public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext())) { var dataProtectionProvider = Startup.DataProtectionProvider; this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); // do other configuration } } 

johnso的回答也提供了一个很好的例子,说明如何使用Autofac进行连接。

我有同样的问题,除了我在亚马逊ec2托pipe。 我能够通过转到iis中的应用程序池和(在右键单击之后的高级设置下)设置过程模型 – 加载用户configuration文件= true来解决它。

我遇到了同样的问题( Owin.Security.DataProtection.DpapiDataProtectionProvider在Azure上运行时失败),Staley是正确的,您不能使用DpapiDataProtectionProvider

如果使用OWIN启动类 ,则可以避免使用自己的IDataProtectionProvider ,而应使用GetDataProtectionProvider方法。

例如,使用Autofac:

 internal static IDataProtectionProvider DataProtectionProvider; public void ConfigureAuth(IAppBuilder app) { // ... DataProtectionProvider = app.GetDataProtectionProvider(); builder.Register<IDataProtectionProvider>(c => DataProtectionProvider) .InstancePerLifetimeScope(); // ... }