2017-03-21 16 views
2

リンクでユーザーの電子メールを確認する必要がありますが、この操作でASP.Net IDが失敗します。電子メールの確認が失敗します

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を使用します。

+0

どのように失敗しますか?それはどこで失敗するのですか? – Heki

+0

ここでスクリーンショットを投稿します。 –

+0

私はどのラインのラインに沿って考えていたのですが、メッセージはスクリーンショットではなく、何かですが、先に進む: – Heki

答えて

1

まず、トークンが正しいかどうかを判断する必要があります。 あなたの生成トークンで、そのトークンをメモし、その後にデータベースをチェックしてください。

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("[email protected]","me"); 
      var smtp = new SmtpClient 
      { 
       Host = "smtp.mail.com", 
       Port = 25, 
       UseDefaultCredentials = false, 
       Credentials = new System.Net.NetworkCredential("[email protected]", "password"), 
       EnableSsl = true 
      }; 
      // Enter seders User name and password 

      smtp.Send(mail); 

      return System.Threading.Tasks.Task.FromResult(0); 
     } 

電子メールの確認リンクが表示されたら、それはcallbackurlと一致する必要があります。 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"); 
     } 

この方法では、コード変数がIDテーブルのコードと一致する必要があります。

また、Identity Frameworkでは重要な問題があります。 MVCには依存性のある注入コンテナなどはありません。独自のIoCを作成する必要があります。私はいつもこれを行うために構造マップを好む。生涯のマネージャーは他よりも優れているので(ninject、unityなど)。また、データベースまたはセッションマネージャへのリクエストを減らすために、現在のユーザーオブジェクトを使用しています。私のMVCレジストリで

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())); } 
     } 
    } 

(のStructureMapのドキュメントを確認してください)

は、私はいつもにも、私は、オブジェクト参照の問題とタイトを防ぐため、同じユーザーに対して同じオブジェクトを使用して、私はこれで

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)); 
     } 
    } 

に必要なすべてを登録しますカップリングの問題もある。

+0

私はすべて同じコードを持っていますが、リンク内のトークンが別のトークンで置き換えられるという私の問題です。私。 '+'は空白で置き換えられます。 –

+0

そのすべてが依存しています。私は依存性を注入する前にこの問題を抱えています。 mvcでは、依存関係のための解決策はありません。すべてのユーザーマネージャの依存関係を注入する必要があります。 –

+0

あなたがリクエストする度に、新しいusermanagerオブジェクトの作成があり、それは主な問題です。 –

2

+符号が失われると、UrlEncodingの問題を示します。 +は空白を表し、それを保存したい場合は、codeのコンテンツをエンコードしてから、UserManager.ConfirmEmailAsyncを呼び出す直前にConfirmEmailメソッドでデコードします。

+は、復号化されたときに%2Bになり、逆の場合は逆になります。

System.Web名前空間のHttpUtility.UrlEncode()HttpUtility.UrlDecode()を使用してください。

+0

Url.Actionを使用すると、背後でエンコーディングが行われます。私たちがそれを使うなら、エンコーディングとデコードの必要はありません。最初の答えは最高です –

関連する問題