Asp.net 生成重置密码令牌在Azure网站中不起作用
我正在使用ASP.NET 5附带的内置Asp.net 生成重置密码令牌在Azure网站中不起作用,asp.net,asp.net-mvc,azure,Asp.net,Asp.net Mvc,Azure,我正在使用ASP.NET 5附带的内置UserManager类在我的站点上实现重置密码功能 在我的开发环境中,一切正常。但是,一旦我在作为Azure网站运行的生产站点中尝试了它,我会遇到以下异常: 系统.安全.加密.加密异常:数据保护操作失败。这可能是由于没有为当前线程的用户上下文加载用户配置文件造成的,这可能是线程正在模拟的情况 这是我如何设置UserManager实例的: var provider = new Microsoft.Owin.Security.DataProtection.Dp
UserManager
类在我的站点上实现重置密码功能
在我的开发环境中,一切正常。但是,一旦我在作为Azure网站运行的生产站点中尝试了它,我会遇到以下异常:
系统.安全.加密.加密异常:数据保护操作失败。这可能是由于没有为当前线程的用户上下文加载用户配置文件造成的,这可能是线程正在模拟的情况
这是我如何设置UserManager
实例的:
var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider(SiteConfig.SiteName);
UserManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<User>(provider.Create(ResetPasswordPurpose));
不幸的是,当它在Azure上运行时,我得到了上面的异常
我在谷歌上搜索了一下,找到了这个。然而,它根本不起作用,我仍然得到同样的例外
根据链接,这与会话令牌在Azure这样的web场上不起作用有关。DpapiDataProtectionProvider使用的会话令牌在web场/云环境中无法正常工作,因为加密数据只能由加密数据的机器解密。您需要的是一种加密数据的方法,这样您的环境中的任何机器都可以对数据进行解密。遗憾的是,ASP.NET Identity 2.0不包括DpapiDataProtectionProvider以外的任何其他IPProtectionProvider实现。然而,你自己动手并不难 一种选择是利用以下资源:
公共类MachineKeyProtectionProvider:IDataProtectionProvider
{
公共IDataProtector创建(参数字符串[]用途)
{
返回新的MachineKeyDataProtector(用途);
}
}
公共类MachineKeyDataProtector:IDataProtector
{
专用只读字符串[]\u;
公共MachineKeyDataProtector(字符串[]用途)
{
_目的=目的;
}
公共字节[]保护(字节[]用户数据)
{
返回MachineKey.Protect(用户数据,用途);
}
公共字节[]取消保护(字节[]受保护数据)
{
返回MachineKey.Unprotect(protectedData,_目的);
}
}
要使用此选项,您需要遵循几个步骤
步骤1
修改代码以使用MachineKeyProtectionProvider
using Microsoft.AspNet.Identity.Owin;
// ...
var provider = new MachineKeyProtectionProvider();
UserManager.UserTokenProvider = new DataProtectorTokenProvider<User>(
provider.Create("ResetPasswordPurpose"));
使用Microsoft.AspNet.Identity.Owin;
// ...
var provider=new MachineKeyProtectionProvider();
UserManager.UserTokenProvider=新的DataProtectorTokenProvider(
创建(“ResetPasswordPurpose”);
步骤2
web场/云环境中所有机器的价值。这听起来很吓人,但这是我们之前无数次执行的步骤,目的是让ViewState验证在web场中正常工作(它也使用DPAPI)。除了在amazon ec2上托管之外,我遇到了相同的问题。
我可以通过进入IIS中的应用程序池并(右键单击后在“高级设置”下)设置进程模型-load user profile=true来解决此问题。我遇到了相同的问题(
Owin.Security.DataProtection.DpapiDataProtectionProvider在Azure上运行时失败),Staley是正确的,您不能使用DpapiDataProtectionProvider
如果正在使用,可以避免滚动自己的IDataProtectionProvider
,而是使用IAppBuilder
的GetDataProtectionProvider
方法
例如,使用Autofac:
internal static IDataProtectionProvider DataProtectionProvider;
public void ConfigureAuth(IAppBuilder app)
{
// ...
DataProtectionProvider = app.GetDataProtectionProvider();
builder.Register<IDataProtectionProvider>(c => DataProtectionProvider)
.InstancePerLifetimeScope();
// ...
}
内部静态IDataProtectionProvider DataProtectionProvider;
public void ConfigureAuth(IAppBuilder应用程序)
{
// ...
DataProtectionProvider=app.GetDataProtectionProvider();
注册器(c=>DataProtectionProvider)
.InstancePerLifetimeScope();
// ...
}
考虑使用IAppBuilder.GetDataProtectionProvider()
而不是声明新的DpapiDataProtectionProvider
与您类似,我通过如下配置我的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),
};
}
}
…然后从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
}
}
公共类UserManager:UserManager
{
public UserManager():base(新的UserStore(新的MyDbContext()))
{
var dataProtectionProvider=Startup.dataProtectionProvider;
this.UserTokenProvider=
新的DataProtectorTokenProvider(dataProtectionProvider.Create(“ASP.NET标识”);
//执行其他配置
}
}
约翰索的回答也提供了一个很好的例子,说明了如何使用Autofac将其连接起来。报道。这对asp.net团队来说是一个很好的反馈,您会提出一个问题吗?这是一个bug吗ResetPasswordPurpose
应该是字符串,对吗?像“重置密码用途”
?@Chris:太棒了!!这救了我一天。我只是感到沮丧,因为我的DpapiDataProtectionProvider一次又一次地返回相同的令牌(针对不同的用户)。你的解决方案很有魅力。非常感谢!!我也可以确认这是我的修复方法。谢谢天啊!我爱你!谢谢太棒了!:)请对此问题进行表决以修复此问题。我在Azure VM上运行时遇到相同的错误。这是由同样的事情引起的吗?或者这应该是一个新的SO问题?这是否解决了DPAPI不能在顶部答案中提到的web场中工作的问题?否,但它允许ASP.NET Identity 2.0在Azure网站(web应用)中工作,我相信这是问题的目的。在Azure中,最重要的答案有它自己的问题,因为设置MachineKey带来了它自己的挑战:Thank@Loren,当您有一个自定义的Identity实现时,它也能很好地为我工作。非常感谢@LorenPaulsen,你救了我一天。Azure上的webfarms或VM(您可以设置/同步机器密钥)和Azure应用程序服务(Azure网站)之间确实存在差异,您无法设置机器密钥。这个答案
public partial class Startup
{
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
// other stuff.
}
}
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
}
}