繁体   English   中英

使用 OWIN / Katana 在 Azure 上进行数据保护操作不成功

[英]The data protection operation was unsuccessful on Azure using OWIN / Katana

我正在尝试在运行于 Azure 的基于 OWIN/Katana 的 ASP.NET MVC 网站上实施密码重置。

它在本地运行时工作正常但在生产中失败。

我创建了一个 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[] optionalEntropy, DataProtectionScope 范围) 在 System.Security.Cryptography.DpapiDataProtector.ProviderProtect(Byte[] userData) (Byte[] userData) at Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect(Byte[] userData) at 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 ()

当我尝试在Web API中使用ASP .Net标识和自定义登录功能生成令牌时,我遇到了同样的问题。

“数据保护操作不成功。这可能是由于没有为当前线程的用户上下文加载用户配置文件引起的,这可能是线程模拟时的情况。”

我所做的只是在Microsoft Azure中创建一个名为WEBSITE_LOAD_USER_PROFILE的应用程序设置,并将其设置为1.该解决方案适用于我。

你可以在这里看到细节

请看我对这个问题的答案 利用IAppBuilder.GetDataProtectionProvider()可以实现更简单的解决方案

我找到了解决方案。 我不确定是否所有步骤都是必要的,但现在我的应用程序完美运行:

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

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

这对我有用:)我希望它也适合你

如果主机服务器是虚拟机,则可能正是错误消息所说的内容。 检查IIS中的应用程序池是否确实将“ Load User Profile设置为“true”,如下所示:

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

在此输入图像描述

我把这个放在冰上一段时间,但被迫回到它。 我在这里找到了解决方案: 生成重置密码令牌在Azure网站中不起作用

我在共享主机提供商处发生此错误,该行:

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

从Owin管道获取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; }
    }

在我和其他两个人弄乱了 dayS 的这个错误之后,我们在 IIS 中发现了一些有趣的东西。如果切换了加载用户配置文件,则会在 applicationhost.config 中创建以下内容

loadUserProfile="true"

但是当你关闭它时它也可以工作,但是现在这条线

loadUserProfile="false"

已添加。 所以区别在于必须在 applicationhost.config 中写入默认值才能使其工作

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM