确认电子邮件时Identity 2.0无效令牌

时间:2014-11-09 20:24:20

标签: c# asp.net webforms asp.net-identity

在我的确认页面上,我在manager.ConfirmEmail(userID,code)

上收到无效的令牌错误
        protected void Page_Load(object sender, EventArgs e)
        {
            string code = IdentityHelper.GetCodeFromRequest(Request);
            string userId = IdentityHelper.GetUserIdFromRequest(Request);
            if (code != null && userId != null)
            {
                var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
                var result = manager.ConfirmEmail(userId, code);
                if (result.Succeeded)
                {
                    successPanel.Visible = true;
                    return;
                }
            }
            successPanel.Visible = false;
            errorPanel.Visible = true;
        }

以下是注册用户的代码,一切正常,电子邮件发送:

        protected void CreateUser_Click(object sender, EventArgs e)
        {
            var currentApplicationId = GetApplicationID();

            var manager = new UserManager();
            User user = new User() { UserName = Email.Text, ApplicationId = currentApplicationId, LoweredUserName = Email.Text.ToLower(), Email=Email.Text,LoweredEmail=Email.Text.ToLower() };

            user.IsApproved = true;

            IdentityResult result = manager.Create(user, Password.Text);
            if (result.Succeeded)
            {
                var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("SynergyWebApp2015");
                //UserManager<User> userManager = new UserManager<User>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<User>());
                //userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<User>(provider.Create(user.Id));
                manager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<User>(provider.Create("ConfirmUser"));
                // -----------------------EMAIL----------------------------
                string code =  manager.GenerateEmailConfirmationToken(user.Id);
                string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
                Context.GetOwinContext().GetUserManager<ApplicationUserManager>().SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
                ///--------------------------------------------------------


                    ErrorMessage.Text = "An email has been sent to your account. Please view the email and confirm your account to complete the registration process.";
            }
            else 
            {
                ErrorMessage.Text = result.Errors.FirstOrDefault();
            }
        }
        private Guid GetApplicationID()
        {
            using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
            {
                string queryString = "SELECT ApplicationId from aspnet_Applications WHERE ApplicationName = '/'"; //Set application name as in database

                SqlCommand command = new SqlCommand(queryString, connection);
                command.Connection.Open();

                var reader = command.ExecuteReader();
                while (reader.Read())
                {
                    return reader.GetGuid(0);
                }

                return Guid.NewGuid();
            }
        }

这是我的用户管理器类

public class UserManager : UserManager<User>
{
    public UserManager()
        : base(new UserStore<User>(new ApplicationDbContext()))
    {
       /* var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Sample");
        UserManager<User> userManager = new UserManager<User>(new UserStore<User>());
        userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<User>(provider.Create("EmailConfirmation"));
        */
        this.PasswordHasher = new SQLPasswordHasher();
    }
}


public class SQLPasswordHasher : PasswordHasher
{
    public override string HashPassword(string password)
    {
        return base.HashPassword(password);
    }

    public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
    {
        string[] passwordProperties = hashedPassword.Split('|');
        if (passwordProperties.Length != 3)
        {
            return base.VerifyHashedPassword(hashedPassword, providedPassword);
        }
        else
        {
            string passwordHash = passwordProperties[0];
            int passwordformat = 1;
            string salt = passwordProperties[2];
            if (String.Equals(EncryptPassword(providedPassword, passwordformat, salt), passwordHash, StringComparison.CurrentCultureIgnoreCase))
            {
                return PasswordVerificationResult.SuccessRehashNeeded;
            }
            else
            {
                return PasswordVerificationResult.Failed;
            }
        }
    }

    //This is copied from the existing SQL providers and is provided only for back-compat.
    private string EncryptPassword(string pass, int passwordFormat, string salt)
    {
        if (passwordFormat == 0) // MembershipPasswordFormat.Clear
            return pass;

        byte[] bIn = Encoding.Unicode.GetBytes(pass);
        byte[] bSalt = Convert.FromBase64String(salt);
        byte[] bRet = null;

        if (passwordFormat == 1)
        { // MembershipPasswordFormat.Hashed 
            HashAlgorithm hm = HashAlgorithm.Create("SHA1");
            if (hm is KeyedHashAlgorithm)
            {
                KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm;
                if (kha.Key.Length == bSalt.Length)
                {
                    kha.Key = bSalt;
                }
                else if (kha.Key.Length < bSalt.Length)
                {
                    byte[] bKey = new byte[kha.Key.Length];
                    Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
                    kha.Key = bKey;
                }
                else
                {
                    byte[] bKey = new byte[kha.Key.Length];
                    for (int iter = 0; iter < bKey.Length; )
                    {
                        int len = Math.Min(bSalt.Length, bKey.Length - iter);
                        Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
                        iter += len;
                    }
                    kha.Key = bKey;
                }
                bRet = kha.ComputeHash(bIn);
            }
            else
            {
                byte[] bAll = new byte[bSalt.Length + bIn.Length];
                Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
                Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
                bRet = hm.ComputeHash(bAll);
            }
        }

        return Convert.ToBase64String(bRet);
    }

}

public static class IdentityHelper
{
    // Used for XSRF when linking external logins
    public const string XsrfKey = "XsrfId";

    public static void SignIn(UserManager manager, User user, bool isPersistent)
    {
        IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
        authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        var identity = manager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
        authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }

    public const string ProviderNameKey = "providerName";
    public static string GetProviderNameFromRequest(HttpRequest request)
    {
        return request[ProviderNameKey];
    }

    public static string GetExternalLoginRedirectUrl(string accountProvider)
    {
        return "/IdentityAccount/RegisterExternalLogin.aspx?" + ProviderNameKey + "=" + accountProvider;
    }

    private static bool IsLocalUrl(string url)
    {
        return !string.IsNullOrEmpty(url) && ((url[0] == '/' && (url.Length == 1 || (url[1] != '/' && url[1] != '\\'))) || (url.Length > 1 && url[0] == '~' && url[1] == '/'));
    }

    public static void RedirectToReturnUrl(string returnUrl, HttpResponse response)
    {
        if (!String.IsNullOrEmpty(returnUrl) && IsLocalUrl(returnUrl))
        {
            response.Redirect(returnUrl);
        }
        else
        {
            response.Redirect("~/");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我修好了。

string code =  manager.GenerateEmailConfirmationToken(user.Id);

需要:

string code =  Context.GetOwinContext().GetUserManager<ApplicationUserManager>().GenerateEmailConfirmationToken(user.Id);

这个答案对于使用.net关于迁移的文章从SQL成员转换到Identity 2.0非常有用。