Azureで実行されているOWIN /カタナベースのASP.NET MVC Webサイトにパスワードリセットを実装しようとしています。
ローカルで実行すると正常に機能しますが、本番環境では失敗します。
UserTokenプロバイダーを作成します
userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"))
しかし、次のようにトークンを生成しようとすると
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
次の例外が発生します。
System.Security.Cryptography.CryptographicException:データ保護操作は失敗しました。これは、現在のスレッドのユーザーコンテキストに対してユーザープロファイルが読み込まれていないことが原因である可能性があります。これは、スレッドが偽装している場合に発生することがあります。 System.Security.Cryptography.DataProtector.ProtectでSystem.Security.Cryptography.DpapiDataProtector.ProviderProtect(Byte [] userData)でSystem.Security.Cryptography.ProtectedData.Protect(Byte [] userData、Byte [] optionalEntropy、DataProtectionScope scope)で(Byte [] userData)at Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect(Byte [] userData)at Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider 2.d__0.MoveNext()---前のスタックトレースの終わり例外がスローされた場所--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)at Microsoft.AspNet.Identity.UserManager`2.d__e9.MoveNext ()
Web APIでASP .Net IDとカスタムログイン関数を使用してトークンを生成しようとすると、同じ問題が発生します。
「データ保護操作に失敗しました。これは、現在のスレッドのユーザーコンテキストにユーザープロファイルが読み込まれていないことが原因である可能性があります。これは、スレッドが偽装している場合に発生することがあります。」
私がしたことは、単に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 app)を次のように更新します。
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.-次のように、スタートアップクラスのコンストラクタをクリーンアップします。
static Startup()
{
PublicClientId = "self";
}
それは私のために働いた:)私はそれがあなたのためにも働くことを望みます
これをしばらく氷の上に置いたのですが、また戻さざるを得ませんでした。私はここに解決策を見つけました: リセットパスワードトークンの生成はAzure Webサイトでは機能しません
このエラーは、共有ホスティングプロバイダーで次の行で発生します。
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
エラー。
App_Start/Startup.Auth.csで設定されているように、OwinパイプラインからUserManagerを取得すると、Azureで機能します。これが具体的にどのように機能するかはわかりません。 DpApiは、最初のリンクで説明されているソリューションを使用してAzureで動作するはずです。
DpApiの静的マシンキーがWeb.configに設定されている場合、すべてのサーバーマシンは、Webファーム内の別のマシンによって作成された暗号化データを復号化できます。
(標準テンプレートで指定されているコード-AccountController.csから)
private UserManager userManager;
public UserManager UserManager
{
get { return userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>(); }
private set { userManager = value; }
}