邮箱确认失败
Email confirmation fails
我需要通过 link 确认用户的电子邮件,但 ASP.Net 身份验证失败。下面的代码是我如何生成令牌:
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); // Return Opd+0yNG++ZXFpRS19A8j8OgI7dzCAKTYWotHYvuu0nyYsH4SIQS+bHwkbmqQDlwvGAy5fyxxUsu4yIzHwF+PD6QNPU+PwBnIDUGMC9++FkMlqegqHVKpA59qvbokfI0yByYqLoZfD1EUpWExddDN0BN/SVNSgOKlyzd928k+k4O2/TnfSf/JFj8x1NUKuaj
以及我如何尝试检查和确认它:
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
Logger.Error(string.Format("userId: {0}, code: {1}", userId, code));
return View("Error");
}
// args values: userId: b96bf253-62e1-4c5e-bf5f-5bc527df9fd9 code: Opd 0yNG ZXFpRS19A8j8OgI7dzCAKTYWotHYvuu0nyYsH4SIQS bHwkbmqQDlwvGAy5fyxxUsu4yIzHwF PD6QNPU PwBnIDUGMC9 FkMlqegqHVKpA59qvbokfI0yByYqLoZfD1EUpWExddDN0BN/SVNSgOKlyzd928k k4O2/TnfSf/JFj8x1NUKuaj
var result = await UserManager.ConfirmEmailAsync(userId, code);
if (result.Succeeded) // This is false
{
return View("ConfirmEmail");
}
Logger.Error(string.Concat<string>(result.Errors)); // Wrong marker
return View("Error");
}
我在调试器中没有检查到空值。为什么会失败?
P.S。如果它很重要,我会使用 Npgsql,除此之外,一切都很完美。
首先您必须确定令牌是否正确。
在您生成的令牌上,记下该令牌并在之后检查您的数据库。
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
UserManager.EmailService = new EmailService();
await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
这也是我的电子邮件服务以供检查。
public class EmailService : IIdentityMessageService
{
public System.Threading.Tasks.Task SendAsync(IdentityMessage message)
{
// Plug in your email service here to send an email.
var mail = new MailMessage
{
Subject = message.Subject,
Body = message.Body,
IsBodyHtml = true
};
mail.To.Add(message.Destination);
mail.From = new MailAddress("me@mail.com","me");
var smtp = new SmtpClient
{
Host = "smtp.mail.com",
Port = 25,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential("me@mail.com", "password"),
EnableSsl = true
};
// Enter seders User name and password
smtp.Send(mail);
return System.Threading.Tasks.Task.FromResult(0);
}
当您收到电子邮件检查link时,它必须与回调url匹配。当你点击 url 这个方法应该被调用。
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
return View("Error");
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
在此方法中,您必须看到代码变量与您的身份代码匹配 table。
身份框架也存在重要问题。开箱即用的 MVC 上没有依赖注入容器等。您必须创建自己的 IoC。我总是喜欢用结构图来做这件事。因为终身经理比其他人更好(ninject,团结等)。此外,我正在使用当前用户对象来减少对数据库或会话管理器的请求。
public class CurrentUser : ICurrentUser
{
private readonly ApplicationDbContext _context;
private readonly IIdentity _identity;
private ApplicationUser _user;
public CurrentUser(IIdentity identity, ApplicationDbContext context)
{
_identity = identity;
_context = context;
}
public ApplicationUser User
{
get { return _user ?? (_user = _context.Users.Find(_identity.GetUserId())); }
}
}
在我的 MVC 注册表中(请检查结构图文档),我在
上注册了我需要的所有内容
public class MvcRegistry : Registry
{
public MvcRegistry()
{
For<BundleCollection>().Use(BundleTable.Bundles);
For<RouteCollection>().Use(RouteTable.Routes);
For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>();
For<DbContext>().Use(() => new ApplicationDbContext());
For<IAuthenticationManager>().Use(() => HttpContext.Current.GetOwinContext().Authentication);
For<HttpSessionStateBase>().Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
For<HttpServerUtilityBase>().Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server));
}
}
有了这个,我总是为同一个用户使用同一个对象,我也防止了对象引用问题和紧耦合问题。
当 +
符号丢失时,表示 UrlEncoding 问题。 +
代表一个空格,如果你想保留它,你应该编码你的 code
内容,然后在调用 UserManager.ConfirmEmailAsync
.[=20 之前在你的 ConfirmEmail
方法中解码它=]
编码时,+
变为 %2B
,解码时则相反。
使用 System.Web
命名空间中的 HttpUtility.UrlEncode()
和 HttpUtility.UrlDecode()
。
我需要通过 link 确认用户的电子邮件,但 ASP.Net 身份验证失败。下面的代码是我如何生成令牌:
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); // Return Opd+0yNG++ZXFpRS19A8j8OgI7dzCAKTYWotHYvuu0nyYsH4SIQS+bHwkbmqQDlwvGAy5fyxxUsu4yIzHwF+PD6QNPU+PwBnIDUGMC9++FkMlqegqHVKpA59qvbokfI0yByYqLoZfD1EUpWExddDN0BN/SVNSgOKlyzd928k+k4O2/TnfSf/JFj8x1NUKuaj
以及我如何尝试检查和确认它:
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
Logger.Error(string.Format("userId: {0}, code: {1}", userId, code));
return View("Error");
}
// args values: userId: b96bf253-62e1-4c5e-bf5f-5bc527df9fd9 code: Opd 0yNG ZXFpRS19A8j8OgI7dzCAKTYWotHYvuu0nyYsH4SIQS bHwkbmqQDlwvGAy5fyxxUsu4yIzHwF PD6QNPU PwBnIDUGMC9 FkMlqegqHVKpA59qvbokfI0yByYqLoZfD1EUpWExddDN0BN/SVNSgOKlyzd928k k4O2/TnfSf/JFj8x1NUKuaj
var result = await UserManager.ConfirmEmailAsync(userId, code);
if (result.Succeeded) // This is false
{
return View("ConfirmEmail");
}
Logger.Error(string.Concat<string>(result.Errors)); // Wrong marker
return View("Error");
}
我在调试器中没有检查到空值。为什么会失败?
P.S。如果它很重要,我会使用 Npgsql,除此之外,一切都很完美。
首先您必须确定令牌是否正确。 在您生成的令牌上,记下该令牌并在之后检查您的数据库。
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
UserManager.EmailService = new EmailService();
await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
这也是我的电子邮件服务以供检查。
public class EmailService : IIdentityMessageService
{
public System.Threading.Tasks.Task SendAsync(IdentityMessage message)
{
// Plug in your email service here to send an email.
var mail = new MailMessage
{
Subject = message.Subject,
Body = message.Body,
IsBodyHtml = true
};
mail.To.Add(message.Destination);
mail.From = new MailAddress("me@mail.com","me");
var smtp = new SmtpClient
{
Host = "smtp.mail.com",
Port = 25,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential("me@mail.com", "password"),
EnableSsl = true
};
// Enter seders User name and password
smtp.Send(mail);
return System.Threading.Tasks.Task.FromResult(0);
}
当您收到电子邮件检查link时,它必须与回调url匹配。当你点击 url 这个方法应该被调用。
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
return View("Error");
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
在此方法中,您必须看到代码变量与您的身份代码匹配 table。
身份框架也存在重要问题。开箱即用的 MVC 上没有依赖注入容器等。您必须创建自己的 IoC。我总是喜欢用结构图来做这件事。因为终身经理比其他人更好(ninject,团结等)。此外,我正在使用当前用户对象来减少对数据库或会话管理器的请求。
public class CurrentUser : ICurrentUser
{
private readonly ApplicationDbContext _context;
private readonly IIdentity _identity;
private ApplicationUser _user;
public CurrentUser(IIdentity identity, ApplicationDbContext context)
{
_identity = identity;
_context = context;
}
public ApplicationUser User
{
get { return _user ?? (_user = _context.Users.Find(_identity.GetUserId())); }
}
}
在我的 MVC 注册表中(请检查结构图文档),我在
上注册了我需要的所有内容public class MvcRegistry : Registry
{
public MvcRegistry()
{
For<BundleCollection>().Use(BundleTable.Bundles);
For<RouteCollection>().Use(RouteTable.Routes);
For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>();
For<DbContext>().Use(() => new ApplicationDbContext());
For<IAuthenticationManager>().Use(() => HttpContext.Current.GetOwinContext().Authentication);
For<HttpSessionStateBase>().Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
For<HttpContextBase>().Use(() => new HttpContextWrapper(HttpContext.Current));
For<HttpServerUtilityBase>().Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server));
}
}
有了这个,我总是为同一个用户使用同一个对象,我也防止了对象引用问题和紧耦合问题。
当 +
符号丢失时,表示 UrlEncoding 问题。 +
代表一个空格,如果你想保留它,你应该编码你的 code
内容,然后在调用 UserManager.ConfirmEmailAsync
.[=20 之前在你的 ConfirmEmail
方法中解码它=]
编码时,+
变为 %2B
,解码时则相反。
使用 System.Web
命名空间中的 HttpUtility.UrlEncode()
和 HttpUtility.UrlDecode()
。