Операция защиты данных была безуспешной на Azure с использованием OWIN/Katana
Я пытаюсь реализовать сброс пароля на веб-сайте ASP.NET MVC на базе OWIN/Katana, работающем в Azure.
Он работает нормально при локальном запуске, но не работает.
Я создаю UserToken Provider
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 [] необязательная энтропия, область DataProtectionScope) в System.Security.Cryptography.DpapiDataProtector.ProviderProtect(Byte [] userData) в System.Security.ataProtector(Byte [] userData) в Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect(Byte [] userData) в Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider 2.d__0.MoveNext() --- Конец трассировки стека из предыдущего расположение, в котором было сгенерировано исключение --- в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача-задача) в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача-задача) в Microsoft.AspNet.Identity2.Neager.()
Ответы
Ответ 1
У меня та же проблема, когда я пытаюсь сгенерировать токен с удостоверением ASP.Net и пользовательской функцией входа в систему в веб-API.
"Операция защиты данных была неудачной. Это могло быть вызвано тем, что профиль пользователя не загружен для пользовательского контекста текущего потока, что может быть в случае, когда поток исполняет роль другого".
Я просто создал параметр приложения с именем WEBSITE_LOAD_USER_PROFILE
в Microsoft Azure и установил его на 1. Это решение работает для меня.
Вы можете увидеть детали здесь
Ответ 2
Посмотрите мой мой ответ на этот вопрос. Более простое решение может быть достигнуто за счет использования IAppBuilder.GetDataProtectionProvider()
Ответ 3
Я нашел решение. Я не совсем уверен, что для этого нужны все шаги, но теперь мое приложение отлично работает:
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"/>
в configSections node. И
<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>
как обычный node.
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";
}
Это сработало для меня:) Я надеюсь, что это сработает и для вас.
Ответ 4
Я положил это на лед на некоторое время, но был вынужден вернуться к нему. Я нашел решение здесь:
Генерирование reset токена паролей не работает на Azure Website
Ответ 5
Эта ошибка возникает у меня на общем хостинг-провайдере в строке:
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);
}
}
}
Эт вуаля! Задача решена. Просто помните, что в вашем методе контроллера паролей reset вам также придется использовать этого провайдера, иначе вы получите ошибку Invalid Token
.
Ответ 6
Если хост-сервер является виртуальной машиной, это может быть именно то, что написано в сообщении об ошибке. Проверьте, действительно ли для пула приложений в IIS установлено значение Load User Profile
установленное в значение true, как исключение:
![enter image description here]()
Ответ 7
Получение UserManager из Owin Pipeline, как установлено в 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; }
}