我正在尝试在Azure中运行的基于OWIN / Katana的ASP.NET MVC网站上实现密码重置。
在本地运行时工作正常但在生产中失败。
我创建了一个UserToken提供程序
userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"))
但是当我尝试按如下方式生成令牌时
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
我得到以下例外。
System.Security.Cryptography.CryptographicException:数据 保护操作不成功。这可能是由于 没有为当前线程的用户加载用户配置文件 上下文,当线程模仿时可能就是这种情况。 在System.Security.Cryptography.ProtectedData.Protect(Byte [] userData,Byte [] optionalEntropy,DataProtectionScope scope) 在System.Security.Cryptography.DpapiDataProtector.ProviderProtect(Byte [] 用户数据) 在System.Security.Cryptography.DataProtector.Protect(Byte [] userData) 在Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect(Byte [] 用户数据) 在Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider 2.d__0.MoveNext() ---从抛出异常的先前位置开始的堆栈跟踪结束--- 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) 在Microsoft.AspNet.Identity.UserManager`2.d__e9.MoveNext()
答案 0 :(得分:9)
当我尝试在Web API中使用ASP .Net标识和自定义登录功能生成令牌时,我遇到了同样的问题。
“数据保护操作失败了。这可能是 由于没有为当前线程加载用户配置文件而导致 用户上下文,当线程模仿时可能就是这种情况。“
我所做的只是在Microsoft Azure中创建一个名为WEBSITE_LOAD_USER_PROFILE
的应用程序设置,并将其设置为1.该解决方案适用于我。
您可以看到详细信息here
答案 1 :(得分:5)
请参阅此问题的my answer。利用IAppBuilder.GetDataProtectionProvider()
答案 2 :(得分:4)
我找到了解决方案。我不完全确定所有步骤是否都有必要,但现在我的应用程序运行正常:
1.-更新您的web.config以支持securityTokenHandlers
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<securityTokenHandlers>
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler,
System.IdentityModel, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089" />
<add
type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=B77A5C561934E089">
<sessionTokenRequirement lifetime="00:30:00"></sessionTokenRequirement>
</add>
</securityTokenHandlers>
</identityConfiguration>
作为常规节点。 2.-在您的Startup.Auth.cs文件中,更新您的ConfigureAuth(IAppBuilder应用程序),如下所示:
public void ConfigureAuth(IAppBuilder app)
{
UserManagerFactory = () =>
{
var userManager = new UserManager<SIAgroUser>(new UserStore<UserType>(new SIAgroUserDbContext()));
IDataProtectionProvider provider = app.GetDataProtectionProvider();
//userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<UserType>(provider.Create("PasswordReset") );
if (provider != null)
{
userManager.UserTokenProvider = new DataProtectorTokenProvider<UsertType, string>(provider.Create("PasswordReset"));
}
return userManager;
};
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication();
}
3.-清理Startup类的构造函数,如下所示:
static Startup()
{
PublicClientId = "self";
}
这对我有用:)我希望它也适合你
答案 3 :(得分:2)
我把这个放在冰上一段时间但被迫回到它身上。我在这里找到了解决方案: Generating reset password token does not work in Azure Website
答案 4 :(得分:2)
我在共享主机提供商处发生此错误:
var provider = new DpapiDataProtectionProvider("SITENAME");
解决方案非常简单。首先将上面的行更改为:
var provider = new MachineKeyProtectionProvider();
然后在我的Utilities命名空间中创建一个新文件,如下所示:
using Microsoft.Owin.Security.DataProtection;
using System.Web.Security;
namespace <yournamespace>.Utilities
{
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);
}
}
}
瞧瞧!问题解决了。请记住,在密码重置控制器方法中,您还必须使用此提供程序,否则您将收到Invalid Token
错误。
答案 5 :(得分:2)
如果主机服务器是虚拟机,则可能正是错误消息所显示的内容。检查您的IIS中的应用程序池是否真的将Load User Profile
设置为true,如异常所示:
答案 6 :(得分:0)
从Owin Pipeline获取UserManager,如App_Start / Startup.Auth.cs中的设置,适用于Azure。 我不确定这是如何具体的。 DpApi应该在Azure中使用第一个链接中描述的解决方案。
如果DpApi在Web.config中设置了静态机器密钥,则所有服务器机器都能够解密由webfarm中另一台机器创建的加密数据。
(标准模板中给出的代码 - 来自AccountController.cs)
private UserManager userManager;
public UserManager UserManager
{
get { return userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>(); }
private set { userManager = value; }
}