2015-09-16 86 views
4

我正在使用Asp.Net身份。當我想通過電子郵件確認令牌確認新用戶時,系統地出現無效令牌錯誤。ASP.NET身份電子郵件確認無效令牌

這裏是我的WebAPI用戶控制器:

public class UsersController : ApiController 
{ 
    private MyContext _db; 
    private MyUserManager _userManager; 
    private MyRoleManager _roleManager; 


public UsersController() 
{ 
    _db = new MyContext(); 
    _userManager = new MyUserManager(new UserStore<MyUser>(_db)); 
    _roleManager = new MyRoleManager(new RoleStore<IdentityRole>(_db)); 
} 

//New user method 
[HttpPost] 
public async Task<HttpResponseMessage> Register([FromBody]PostUserModel userModel) 

{ 
//New user code 
... 

var token = await _userManager.GenerateEmailConfirmationTokenAsync(user.Id); 
      var message = new IdentityMessage(); 
      message.Body = string.Format("Hi {0} !\r\nFollow this link to set your password : \r\nhttps://www.mywebsite.com/admin/users/{1}/reset?token={2}", user.UserName, user.Id, HttpUtility.UrlEncode(token)); 
      message.Subject = "Confirm e-mail"; 
      message.Destination = user.Email; 
      await _userManager.SendEmailAsync(user.Id, message.Subject, message.Body); 

      return Request.CreateResponse(HttpStatusCode.OK, res);      } 
    } 

要確認的電子郵件,我只是在做:

var result = await _userManager.ConfirmEmailAsync(user.Id, token); 

我不這樣做的HttpUtility.UrlDecode因爲的WebAPI本身做它。

我的自定義用戶管理器類:

public class MyUserManager : UserManager<MyUser> 
    { 
     public MyUserManager(IUserStore<MyUser> store) 
      : base(store) 
     {    
      UserValidator = new UserValidator<MyUser>(this) 
      { 
       AllowOnlyAlphanumericUserNames = false, 
       RequireUniqueEmail = true 
      }; 
      // Configure validation logic for passwords 
      PasswordValidator = new PasswordValidator 
      { 
       RequiredLength = 6, 
       RequireNonLetterOrDigit = true, 
       RequireDigit = true, 
       RequireLowercase = true, 
       RequireUppercase = true, 
      }; 
      // Configure user lockout defaults 
      UserLockoutEnabledByDefault = false; 

      EmailService = new EmailService(); 
      SmsService = new SmsService(); 

      var dataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("MyApp"); 

      UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<MyUser>(dataProtectionProvider.Create("UserToken"));    
     } 
    } 
} 

任何想法? 非常感謝

+0

我在我的網站上有類似的問題。基本上DPADI不能在多臺機器上加密/解密。我不得不使用機器密鑰來完成我想要的。你可以在這裏閱讀更多關於它http://stackoverflow.com/a/23661872/1341538 –

+0

謝謝你的回答。我讀過這個,但不幸的是,我在本地主機也遇到了這個問題。 –

+0

可能有一堆原因。我已經寫了關於此之前:http://tech.trailmax.info/2015/05/asp-net-identity-invalid-token-for-password-reset-or-email-confirmation/ – trailmax

回答

0

我已經有同樣的問題,我設法解決它沒有實現基於機器密鑰自定義提供程序。

我已經有了UserTokenProvider這是在UserManager類中設置的類作爲按請求範圍由DI連接。所以每次請求時,我都會創建新的UserTokenProvider

當我檢查源代碼時,我注意到它默認使用DpapiDataProtectionProvider。和DpapiDataProtectionProvider使用的構造函數是:

public DpapiDataProtectionProvider() 
    : this(Guid.NewGuid().ToString()) 
{ 
} 

所以每次DpapiDataProtectionProvider被創建時,它產生用作應用程序名稱的新GUID。

有兩個解決方案來解決這個問題:

  1. 電線它作爲一個單身。
  2. 使它使用一些固定的應用程序名稱。

我決定使用第二個,因爲單身的解決辦法上的應用程序池再次突破回收等

所以現在我的DI註冊(使用簡單注射器)看起來像這樣(仍然使用每個請求即使它可能沒有必要):

container.Register<IUserTokenProvider<ApplicationUser, string>>(() => 
    new DataProtectorTokenProvider<ApplicationUser> 
     (new DpapiDataProtectionProvider("MY APPLICATION NAME").Create("ASP.NET Identity")) 
     { 
      // all user tokens are only valid for 3 hours 
      TokenLifespan = TimeSpan.FromHours(3) 
     }, Lifestyle.Scoped); 

希望這可以幫助別人。

相關問題