asp.net asp - Создание маркера пароля сброса не работает на Azure Website





deploy to (5)


Подумайте об использовании 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),
        };
    }
}

Проблема CodePlex, связанная с выше, фактически ссылается на сообщение в блоге, которое было обновлено с более простым решением проблемы. Он рекомендует сохранять статическую ссылку на 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.

Я выполняю функцию сброса пароля на своем сайте, используя встроенный класс UserManager который поставляется с ASP.NET 5.

Все отлично работает в моей среде разработчиков. Однако, как только я попробую его на рабочем сайте, который работает как веб-сайт Azure, я получаю следующее исключение:

System.Security.Cryptography.CryptographicException : операция защиты данных не увенчалась успехом. Это может быть вызвано отсутствием загрузки профиля пользователя для контекста пользователя текущего потока, что может иметь место, когда поток олицетворяет собой.

Вот как я настраиваю экземпляр UserManager :

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

Затем я генерирую маркер таким образом (для отправки пользователю по электронной почте, чтобы они могли проверить, действительно ли они хотят сбросить свой пароль):

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

К сожалению, когда это работает на Azure, я получаю исключение выше.

Я объединился и нашел это возможное решение . Однако это не сработало, и я все равно получаю такое же исключение.

Согласно ссылке, это имеет какое-то отношение к токенам сеанса, которые не работают на веб-ферме, такой как Azure.




У меня были те же проблемы, кроме того, что я принимал на amazon ec2.
Я смог его решить, перейдя в пул приложений в IIS и (под дополнительными настройками после щелчка правой кнопкой мыши), установив модель процесса - загрузите профиль пользователя = true.




У меня была та же проблема ( Owin.Security.DataProtection.DpapiDataProtectionProvider не работает при Owin.Security.DataProtection.DpapiDataProtectionProvider Azure), а Staley верен, вы не можете использовать DpapiDataProtectionProvider .

Если вы используете стартовые классы OWIN, вы можете не IDataProtectionProvider свой собственный IDataProtectionProvider , а использовать метод IAppBuilder для IAppBuilder .

Например, с Autofac:

internal static IDataProtectionProvider DataProtectionProvider;    

public void ConfigureAuth(IAppBuilder app)
{
    // ...

    DataProtectionProvider = app.GetDataProtectionProvider();

    builder.Register<IDataProtectionProvider>(c => DataProtectionProvider)
        .InstancePerLifetimeScope();

    // ...
}



DpapiDataProtectionProvider использует DPAPI который не будет работать должным образом в среде веб-фермы / облака, поскольку зашифрованные данные могут быть дешифрованы только машиной, которая его зашифровала. Вам нужен способ шифрования данных, чтобы он мог быть расшифрован любой машиной в вашей среде. К сожалению, ASP.NET Identity 2.0 не включает другую реализацию IProtectionProvider, кроме DpapiDataProtectionProvider. Тем не менее, это не так сложно свернуть.

Один из вариантов - использовать класс 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

Синхронизируйте значение MachineKey на всех компьютерах в веб-ферме / облачной среде. Это звучит страшно, но это тот же самый шаг, который мы выполняли бесчисленное количество раз, прежде чем получить правильную работу проверки ViewState в веб-ферме (она также использует DPAPI).




Я предлагаю вам использовать:

 System.Web.HttpContext.Current.Request

Просто запомните System.Web.HttpContext.Current является threadstatic, но если вы не используете дополнительный поток, решение работает.





asp.net asp.net-mvc azure