MVC 5を作成し、Identity 2.0を使用しています。
今、パスワードをリセットしようとしています。しかし、パスワードトークンをリセットすると、常に「無効なトークン」エラーが表示されます。
public class AccountController : Controller
{
public UserManager<ApplicationUser> UserManager { get; private set; }
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
そして、DataProtectorTokenProviderを設定し、
public AccountController(UserManager<ApplicationUser> userManager)
{
//usermanager config
userManager.PasswordValidator = new PasswordValidator { RequiredLength = 5 };
userManager.EmailService = new IddaaWebSite.Controllers.MemberShip.MemberShipComponents.EmailService();
var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider();
userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<ApplicationUser>(provider.Create("UserToken"))
as IUserTokenProvider<ApplicationUser, string>;
UserManager = userManager;
}
メールを送信する前にパスワードをリセットします
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ManagePassword(ManageUserViewModel model)
{
if (Request.Form["email"] != null)
{
var email = Request.Form["email"].ToString();
var user = UserManager.FindByEmail(email);
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
//mail send
}
}
メールのリンクをクリックし、passwordresetトークンを取得して使用しています
var result = await UserManager.ResetPasswordAsync(model.UserId, model.PasswordToken, model.NewPassword);
結果は常にfalseであり、「Invalid Token」と表示されます。どこで修正すればよいですか?
UserManager.GeneratePasswordResetTokenAsync()
は、多くの場合、「+」文字を含む文字列を返します。クエリ文字列でパラメータを渡す場合、これが原因です(「+」文字はURLのクエリ文字列のスペースです)。
model.PasswordToken
のスペース文字を「+」文字に置き換えてみてください。
_[HttpPost]
[ValidateAntiForgeryToken]
publicasync Task<ActionResult> ManagePassword(ManageUserViewModel model)
{
if (Request.Form["email"] != null)
{
var email = Request.Form["email"].ToString();
var user = UserManager.FindByEmail(email);
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
//before send mail
token = HttpUtility.UrlEncode(token);
//mail send
}
}
_
そして、パスワードリセットアクションでトークンをデコードHttpUtility.UrlDecode(token);
データベースのAspNetUsersテーブルのユーザーのSecurityStamp列がNULLの場合にも、「無効なトークン」エラーが発生することがわかりました。 SecurityStampは、すぐに使用できるMVC 5 Identity 2.0コードではNULLになりませんが、SecurityStampフィールドの値をクリアするAccountControllerのカスタマイズを行うと、コードにバグが導入されました。
ここで多くの回答は、送信する前にトークンをURLEncodeして、トークン(ベース64エンコード文字列である)がしばしば「+」文字を含むという事実を回避します。ソリューションでは、トークンが「==」で終わることも考慮する必要があります。
私はこの問題に苦労していました。大規模な組織内の多くのユーザーが、電子メールリンク内のURLEncodedスティングを対称的にエンコードおよびデコードしていないScanmail Trustwave Link Validator(r)を使用していたことがわかりました(執筆時点)。
最も簡単な方法は、Mateusz Cisekの回答を使用して、非URLEncodedトークンを送信し、スペース文字を単に+に戻すことです。私の場合、これはangular SPAで行われたため、Javascriptは$routeParams.token.replace(/ /g,'+')
になります。
ここでの注意点は、AJAXを使用してトークンを送信し、独自のクエリ文字列解析アルゴリズムをローリングする場合です。多くの例では、各パラメータを '='に分割します。 'トークンの末尾。正規表現ソリューションのいずれかを使用するか、最初の「=」のみを検索することにより、簡単に回避できます。