web-dev-qa-db-ja.com

IDパスワードリセットトークンが無効です

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」と表示されます。どこで修正すればよいですか?

27
erkan demir

UserManager.GeneratePasswordResetTokenAsync()は、多くの場合、「+」文字を含む文字列を返します。クエリ文字列でパラメータを渡す場合、これが原因です(「+」文字はURLのクエリ文字列のスペースです)。

model.PasswordTokenのスペース文字を「+」文字に置き換えてみてください。

35
Mateusz Cisek
_[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);

20
Tebogo Johannes

データベースのAspNetUsersテーブルのユーザーのSecurityStamp列がNULLの場合にも、「無効なトークン」エラーが発生することがわかりました。 SecurityStampは、すぐに使用できるMVC 5 Identity 2.0コードではNULLになりませんが、SecurityStampフィールドの値をクリアするAccountControllerのカスタマイズを行うと、コードにバグが導入されました。

13
stonefree

ここで多くの回答は、送信する前にトークンをURLEncodeして、トークン(ベース64エンコード文字列である)がしばしば「+」文字を含むという事実を回避します。ソリューションでは、トークンが「==」で終わることも考慮する必要があります。

私はこの問題に苦労していました。大規模な組織内の多くのユーザーが、電子メールリンク内のURLEncodedスティングを対称的にエンコードおよびデコードしていないScanmail Trustwave Link Validator(r)を使用していたことがわかりました(執筆時点)。

最も簡単な方法は、Mateusz Cisekの回答を使用して、非URLEncodedトークンを送信し、スペース文字を単に+に戻すことです。私の場合、これはangular SPAで行われたため、Javascriptは$routeParams.token.replace(/ /g,'+')になります。

ここでの注意点は、AJAXを使用してトークンを送信し、独自のクエリ文字列解析アルゴリズムをローリングする場合です。多くの例では、各パラメータを '='に分割します。 'トークンの末尾。正規表現ソリューションのいずれかを使用するか、最初の「=」のみを検索することにより、簡単に回避できます。

0
Brent