使用OWIN / Katana在Azure上执行的数据保护操作失败

j1dl9f46  于 2023-02-05  发布在  其他
关注(0)|答案(8)|浏览(122)

我正在尝试在Azure中运行的基于OWIN/Katana的ASP .NETMVC网站上实现密码重置。
它在本地运行时工作正常,但在生产中失败。
我创建了一个UserToken提供程序

userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"))

但当我尝试按如下方式生成令牌时

var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user.Id);

我得到以下异常。
System.Security.Cryptography.CryptographicException:数据保护操作未成功。这可能是由于没有为当前线程的用户上下文加载用户配置文件造成的,当线程正在模拟时可能会出现这种情况。at System.Security.Cryptography.ProtectedData.Protect(字节[]用户数据,字节[]可选熵,DataProtectionScope作用域)位于系统.安全.加密.DpapiDataProtector.提供程序保护(Byte[] userData)位于系统.安全.加密.数据保护.保护(字节[]用户数据)在Microsoft.Owin.安全.数据保护.DpapiDataProtector.保护(字节[]用户数据)在Microsoft.AspNet.身份.Owin.数据保护器令牌提供程序2.d__0.移动下一步()---从前一个引发异常的位置开始的堆栈跟踪结尾---在系统.运行时.编译器服务.任务等待.ThrowForNonSuccess(任务任务)在系统.运行时.编译器服务.任务等待.HandleNonSuccessAndDebuggerNotification(任务任务)在Microsoft.AspNet.标识.用户管理器'2.d__e9.MoveNext()

uqjltbpv

uqjltbpv1#

如果主机服务器是虚拟机,则可能与错误消息所述完全相同。请检查IIS中的应用程序池是否真的将Load User Profile设置为true,如异常所示:

  • 在“连接”窗格中,展开服务器名称,然后单击“应用程序池”。
  • 右键单击您池
  • 高级设置

k10s72fa

k10s72fa2#

当我尝试使用ASP.NET标识和Web API中的自定义登录函数生成令牌时,我遇到了同样的问题。
数据保护操作未成功。这可能是由于没有为当前线程的用户上下文加载用户配置文件造成的,当线程正在模拟时可能会出现这种情况。
我所做的只是在Microsoft Azure中创建一个名为WEBSITE_LOAD_USER_PROFILE的应用程序设置,并将其设置为1。
您可以看到详细信息here

b91juud3

b91juud33#

这个问题请参考我的my answer。使用IAppBuilder.GetDataProtectionProvider()可以实现一个简单得多的解决方案

bwleehnv

bwleehnv4#

我找到了一个解决方案。我不确定是否所有的步骤都是必要的,但现在我的应用程序运行得很完美:
1.-更新您的web.config以支持安全令牌处理程序

<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节点中。并且

<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";
}

那对我很有效:)我希望对你也很有效

qf9go6mv

qf9go6mv5#

这个错误发生在我的共享主机提供商,在行:

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错误。

xfyts7mz

xfyts7mz6#

我把这个问题搁置了一段时间,但不得不重新考虑。我在这里找到了解决办法:Generating reset password token does not work in Azure Website

q1qsirdb

q1qsirdb7#

从Owin管道获取UserManager(如App_Start/Startup.Auth.cs中的设置)可在Azure上工作。我不确定具体如何工作。DpApi应在Azure中与第一个链接中描述的解决方案一起工作。
如果DpApi在Web.config中设置了一个静态机器密钥,那么所有服务器机器都将能够解密由网络场中的另一台机器创建的加密数据,这是对这一点的理解。
(code如标准模板中所示-来自AccountController.cs)

private UserManager userManager;
    public UserManager UserManager
    {
        get { return userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>(); }
        private set { userManager = value; }
    }
kupeojn6

kupeojn68#

在我和另外两个人处理这个错误几天后,我们发现IIS中有一些有趣的东西。如果加载用户配置文件被切换,则在applicationhost.config中创建以下内容

loadUserProfile="true"

但是当你关掉它的时候它也能工作,但是现在这条线

loadUserProfile="false"

所以不同之处在于必须在applicationhost.config中写入默认值才能使其工作

相关问题