ASP.NTE MVC 為何IdentityResult ConfirmEmailAsync返回Succeeded總是false的問題排除



最近一直被ASP.NET (.net framework)  MVC Identity2 搞得很久
Succeeded總是返回false

明明寄發跟ID和tocken比對都一致就是一直返回false




終於發現問題點在於

在於我有自己去多設置UserValidate的客製化設定

把這段註解後就恢復正常了...


>~<||| 但我需要這個CustomValidator的客製化設置呀
接續之前此篇

ASP.NET MVC(十一)_ASP.NET Identity使用筆記_初始配置到註冊篇
ASP.NET MVC(十二)_ASP.NET Identity使用筆記_註冊完後的郵件有效性確認





參考此篇建目前還是有問題






將客製化部分加回去研究一下偵錯狀況發現
也有人反映過此issue






主要是因為在做ConfirmEmailAsync 時候又會再跳到
我們自己客製化的CustomUserValidator執行ValidateAsync
此時資料庫已經有此筆record所以又會多判斷導致結果會錯誤判定



這裡稍微調整一下邏輯
首先自動被Identity跟EF創建出來的IdentityDB要記得刪除
等會我們要重新建立

首先針對AspNetUsers資料庫欄位去做一個欄位擴充
去到我們自己新增繼承自IdentityUser的自訂User Class再去做其餘欄位的擴充

public virtual bool IsFirstTimeRequest { get; set; }

有點類似檢查是否為PostBack那種概念

我希望他只要在第一次Request時候再做這個Validate查檢就好了
雖說官方設計認為每次都要觸發這個查檢機制是正常的
但會與我們資料庫互動檢查有衝突

User.cs
預設默認在建構子就給定預設值為true

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;

namespace AgricultureManagementSystem.Models
{
    public class User : IdentityUser
    {
        public virtual string Account { get; set; }
        public virtual string Region { get; set; }

        public virtual bool IsFirstTimeRequest { get; set; }

        public User()
        {
            this.IsFirstTimeRequest = true;
        }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
        {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }

    }
}



之後再去我們自訂的CustomUserValidator.cs中
針對ValidateAsync的override 方法中做邏輯調整

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public override async Task<IdentityResult> ValidateAsync(User user)
{
    IdentityResult result = await base.ValidateAsync(user);

    if (user.IsFirstTimeRequest)
    {
        int cntAccount = _userManager.Users.Where(n => n.Account == user.Account).Count();
        if (cntAccount > 0)
        {
            var errors = result.Errors.ToList();
            //errors.Add("This Account Name already exists");
            result = new IdentityResult(errors);
        }
    }                     
    return result;
}




Email驗證的Action

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[HttpGet]
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(code))
    {
        return View("Error");
    }

    var _user = await UserManager.FindByIdAsync(userId);
    if (_user == null)
    {
        return View("Error");
    }
    _user.IsFirstTimeRequest = false;
    await UserManager.UpdateAsync(_user);
    var result = await UserManager.ConfirmEmailAsync(userId, code);
    return View(result.Succeeded ? "ConfirmEmail" : "Error");
}


最終就可以讓email驗證機制運行正確









Ref:
ConfirmEmailAsync in UserManager does a ton of unrelated actions and validations

Entity Framework 6 Code first Default value

ASP.NET Identity 2.1 Accounts Confirmation, and Password Policy Configuration – Part 2

Asp.NET Identity 2 giving “Invalid Token” error

ASP MVC ConfirmEmailAsync not working

ConfirmEmailAsync() method is not working

留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header