使用MVC中的Controller外部控制器的生成emailConfirmationTokenAsync使用无效的令牌



我已经陷入困境了几天。

我正在使用GenerateEmailConfirmationTokenAsync在控制器外部创建一个令牌(它工作正常(,但是某种程度上我的令牌比使用GenerateEmailConfirmationTokenAsync在控制器中创建的令牌更长,因此ConfirmEmail操作拒绝令牌。(Error: Invalid Token(。我在web.configHttpUtility.UrlEncode上尝试过Machinekey,但我仍然卡住。

如何在控制器ConfirmEmail上清除无效的令牌错误?

这是我的代码:

registeruser(外部控制器(

public async Task RegisterUserAsync()
{
    var store = new UserStore<ApplicationUser>(db);
    var UserManager = new ApplicationUserManager(store);
    var query = from c in db.Customer
                where !(from o in db.Users
                        select o.customer_pk)
                    .Contains(c.customer_pk)
                select c;
    var model = query.ToList();
    if (query != null)
    {
        foreach (var item in model)
        {
            var user = new ApplicationUser { UserName = item.email, Email = item.email, customerId = item.customerId};
            var result = await UserManager.CreateAsync(user);
            if (result.Succeeded)
            {
                string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id);
                SmtpClient client = new SmtpClient();
                MailMessage message = new MailMessage
                {
                    IsBodyHtml = true
                };
                message.Subject = "Confirm Email";
                message.To.Add(item.email1);
                message.Body = "Please confirm your account by clicking <a href="" + callbackUrl + "">here</a>";
                client.SendAsync(message, "userToken");
                //Assign Role User Here
                await UserManager.AddToRoleAsync(user.Id, "Client");
            }
        }
    }
}

sendemailConfirnation方法(外部控制器(

public async Task<string> SendEmailConfirmationTokenAsync(string userID)
{
    var store = new UserStore<ApplicationUser>(db);
    var UserManager = new ApplicationUserManager(store);
    var url = new UrlHelper();
    var provider = new DpapiDataProtectionProvider("MyApp");
    UserManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
        provider.Create("EmailConfirmation"));
    string code = await UserManager.GenerateEmailConfirmationTokenAsync(userID);
    string encodedCode = HttpUtility.UrlEncode(code);
    string callbackUrl = "http://localhost/Accounts/ConfirmEmail?userId=" + userID + "&code=" + encodedCode;
    return callbackUrl;
}

db是

ApplicationdDbContext db = new ApplicationdDbContext();

ConfirmEmail在身份控制器(帐户控制器(中 - 我创建了帐户而不是帐户控制器,但工作正常。

//
// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (userId == null || code == null)
    {
        return View("Error");
    }
    var confirmed = await UserManager.IsEmailConfirmedAsync(userId);
    if (confirmed)
    {
        return RedirectToLocal(userId);
    }
    var result = await UserManager.ConfirmEmailAsync(userId, code); //Here I get the error (Token Invlaid, despite the token and userId being displayed)
    if (result.Succeeded)
    {
        ViewBag.userId = userId;
        ViewBag.code = code;
    }
    return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(SetPasswordViewModel model, string userId, string code)
{
    if (userId == null || code == null)
    {
        return View("Error");
    }
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var result = await UserManager.AddPasswordAsync(userId, model.NewPassword);
    if (result.Succeeded)
    {
        var user = await UserManager.FindByIdAsync(userId);
        if (user != null)
        {
            await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
        }
        return RedirectToLocal(userId);
    }
    ViewBag.userId = userId;
    ViewBag.code = code;
    AddErrors(result);
    return View(model);
}

我已经在此代码中工作了几个小时,但是到目前为止,我还无法解决。感谢您的任何评论或解决方案。这种方法的原因是我必须使用任务调度程序(我正在使用FulentsCheduler,这很好(。

您的问题在此行中:

var provider = new DpapiDataProtectionProvider("MyApp");
UserManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(
    provider.Create("EmailConfirmation"));

DpapiDataProtectionProvider这里与在IIS下运行时使用的身份不同。据我所记得,它使用IIS Web站点的内部名称而不是"MyApp"。还可以通过代表和单身人士对其进行注册,从而有些魔力。

您可以尝试将静态引用保存到数据保护提供商中,并在调度程序代码中使用它。在Startup.Auth.cs类中执行此操作:

public partial class Startup
{
    internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
    public void ConfigureAuth(IAppBuilder app)
    {
        DataProtectionProvider = app.GetDataProtectionProvider();
        // other stuff.
    }
}

然后在您的Usermanager访问此类参考中访问:

public class UserManager : UserManager<ApplicationUser>
{
    public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext()))
    {
        var dataProtectionProvider = Startup.DataProtectionProvider;
        this.UserTokenProvider = 
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        // do other configuration
    }
}

但是,我并不熟悉流利链式的细节,如果在单独的AppDomain中启动进程,它可能不会让您访问此静态变量。但请尝试一下,看看它是如何工作的。

相关内容

  • 没有找到相关文章

最新更新