Asp.net标识令牌不匹配编码问题



我正在尝试使用asp.net身份验证,我在编码/解码方面遇到一些问题。

用户点击忘记密码链接,所以我们调用:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[PassModelStateToTempData]
public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        logger.Info("reset_password attempting for {0}", model.Email);
        var user = await UserManager.FindByNameAsync(model.Email);
        if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
        {
            this.Flash("Please check your email, we have sent you instructions on how to reset your password");
            return RedirectToAction("ForgotPassword");
        }
        string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
        logger.Debug("forgot_password code {0}", code);
        var callbackUrl = Url.Action("ResetPassword", "Session", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
        messagingService.ResetPassword(user.Email, callbackUrl);
        this.Flash("Please check your email, we have sent you instructions on how to reset your password");
        logger.Debug("remind_me successfully send out email to {0} {1}", model.Email, callbackUrl);
        return RedirectToAction("ForgotPassword");
    }
    logger.Info("reset_password failed for {0}", model.Email);
    // If we got this far, something failed, redisplay form
    return RedirectToAction("ForgotPassword");
}

用户收到电子邮件,然后点击链接,所以我们运行:

[HttpGet]
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
    if (code == null)
    {
        this.Flash("Invalid login token, please enter your email address again");
        return RedirectToAction("ForgotPassword");
    }
    var vm = new ResetPasswordViewModel
    {
         Code = code
    };
    return View(vm);
}

我们将令牌传递给视图-我们要求提供电子邮件和密码,然后用户点击post并运行:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return RedirectToAction("ResetPassword");
    }
    var user = await UserManager.FindByNameAsync(model.Email);
    if (user == null)
    {
        logger.Info("reset_password user not found [{0}]", model.Email);
        // Don't reveal that the user does not exist
        return RedirectToAction("ResetPasswordConfirmation", "Session");
    }
    var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
    if (result.Succeeded)
    {
        return RedirectToAction("ResetPasswordConfirmation", "Session");
    }
    AddErrors(result);
    return RedirectToAction("ResetPassword", new { code = model.Code });
}

由于某些原因,令牌似乎不匹配,这里是我得到的令牌的一个示例-为什么情况不同?

标记:

2015-10-14 13:06:52.7545 | |调试控制器。应用程序|forgot_password代码BoUZZ9OS7rEkKMkEJzerWdds4dZLHFTHO/EkjQC2Zr8YJvCyjsXUKBRLZk8jmAqhjyxOzgqOLdJ8P/ji8y+om2ne7bcsLICzcdLSHzrP6BNEr1/+HKvHcYan+JzAX7Ifpgq7casmMj4f9esAdxejLA==

注意大小写的区别:

2015-10-14 13:07:29.7164 |信息|控制器。应用程序|reset_password尝试使用令牌my.email@gmail.com: bouzz9os7rekkmkejzerwdds4dzlhftho/ekjqc2zr8yjvcyjsxukbrlzk8jmaqhjyxozgqoldj8p/ji8y+om2ne7bcsliczcdlshzrp6bner1/+hkvhcyan+jzax7ifpgq7casmmj4f9esadxejla== ->无效令牌。

您的MVC路由设置为生成小写url:

routes.LowercaseUrls = true;

这意味着你的代码也被转换成小写。可能的解决方案如下:

  1. 如果可以(或想要)关闭LowercaseUrls
  2. 使用MVC属性路由,尽管这可能是一个相当大的切换。
  3. 对你来说最简单的选择可能是自己创建URL:

    //Generate the URL without the code parameter
    var callbackUrl = Url.Action(
        "ResetPassword",
        "Session", 
        new { userId = user.Id }, 
        protocol: Request.Url.Scheme);
    //Manually add the code, remembering to encode it
    callbackUrl = callbackUrl + "&code=" HttpUtility.UrlEncode(code);
    

最新更新