ASP.NET MVC第013天_ASP.NET Identity使用筆記_註冊完後的郵件有效性確認

 



註冊完的使用者
通常網站上的操作是會發一個確認通知信
可能有驗證碼
一來是為了確認輸入的email有效性
二來也是再多一份身分有效性驗證

預設我們可以去觀察Identity自動幫我們建立好的資料表結構
就有規劃像是EmailConfirmed , PhoneNumberConfirmed等布林值欄位
就是要我們留意記得再多做這些真實身分認證


針對發信驗證部分
先研究一下UserManager本身封裝的結構
可以看到本身有支援除了Email驗證也包含簡訊的SMS



  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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
#region 組件 Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// D:\SideProjects\AgricultureManagementSystem_Tmp\AgricultureManagementSystem\packages\Microsoft.AspNet.Identity.Core.2.2.3\lib\net45\Microsoft.AspNet.Identity.Core.dll
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Microsoft.AspNet.Identity
{
    //
    // 摘要:
    //     Exposes user related api which will automatically save changes to the UserStore
    //
    // 類型參數:
    //   TUser:
    //
    //   TKey:
    public class UserManager<TUser, TKey> : IDisposable
        where TUser : class, IUser<TKey>
        where TKey : IEquatable<TKey>
    {
        //
        // 摘要:
        //     Constructor
        //
        // 參數:
        //   store:
        //     The IUserStore is responsible for commiting changes via the UpdateAsync/CreateAsync
        //     methods
        public UserManager(IUserStore<TUser, TKey> store);

        //
        // 摘要:
        //     Used to validate users before changes are saved
        public IIdentityValidator<TUser> UserValidator { get; set; }
        //
        // 摘要:
        //     Used to validate passwords before persisting changes
        public IIdentityValidator<string> PasswordValidator { get; set; }
        //
        // 摘要:
        //     Used to create claims identities from users
        public IClaimsIdentityFactory<TUser, TKey> ClaimsIdentityFactory { get; set; }
        //
        // 摘要:
        //     Used to send email
        public IIdentityMessageService EmailService { get; set; }
        //
        // 摘要:
        //     Used to send a sms message
        public IIdentityMessageService SmsService { get; set; }
        //
        // 摘要:
        //     Used for generating reset password and confirmation tokens
        public IUserTokenProvider<TUser, TKey> UserTokenProvider { get; set; }
        //
        // 摘要:
        //     If true, will enable user lockout when users are created
        public bool UserLockoutEnabledByDefault { get; set; }
        //
        // 摘要:
        //     Number of access attempts allowed before a user is locked out (if lockout is
        //     enabled)
        public int MaxFailedAccessAttemptsBeforeLockout { get; set; }
        //
        // 摘要:
        //     Default amount of time that a user is locked out for after MaxFailedAccessAttemptsBeforeLockout
        //     is reached
        public TimeSpan DefaultAccountLockoutTimeSpan { get; set; }
        //
        // 摘要:
        //     Returns true if the store is an IUserTwoFactorStore
        public virtual bool SupportsUserTwoFactor { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserPasswordStore
        public virtual bool SupportsUserPassword { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserSecurityStore
        public virtual bool SupportsUserSecurityStamp { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserRoleStore
        public virtual bool SupportsUserRole { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserLoginStore
        public virtual bool SupportsUserLogin { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserEmailStore
        public virtual bool SupportsUserEmail { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserPhoneNumberStore
        public virtual bool SupportsUserPhoneNumber { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserClaimStore
        public virtual bool SupportsUserClaim { get; }
        //
        // 摘要:
        //     Returns true if the store is an IUserLockoutStore
        public virtual bool SupportsUserLockout { get; }
        //
        // 摘要:
        //     Returns true if the store is an IQueryableUserStore
        public virtual bool SupportsQueryableUsers { get; }
        //
        // 摘要:
        //     Used to hash/verify passwords
        public IPasswordHasher PasswordHasher { get; set; }
        //
        // 摘要:
        //     Returns an IQueryable of users if the store is an IQueryableUserStore
        public virtual IQueryable<TUser> Users { get; }
        //
        // 摘要:
        //     Maps the registered two-factor authentication providers for users by their id
        public IDictionary<string, IUserTokenProvider<TUser, TKey>> TwoFactorProviders { get; }
        //
        // 摘要:
        //     Persistence abstraction that the UserManager operates against
        protected internal IUserStore<TUser, TKey> Store { get; set; }

        //
        // 摘要:
        //     Increments the access failed count for the user and if the failed access account
        //     is greater than or equal to the MaxFailedAccessAttempsBeforeLockout, the user
        //     will be locked out for the next DefaultAccountLockoutTimeSpan and the AccessFailedCount
        //     will be reset to 0. This is used for locking out the user account.
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<AccessFailedAsync>d__144))]
        public virtual Task<IdentityResult> AccessFailedAsync(TKey userId);
        //
        // 摘要:
        //     Add a user claim
        //
        // 參數:
        //   userId:
        //
        //   claim:
        [AsyncStateMachine(typeof(UserManager<,>.<AddClaimAsync>d__101))]
        public virtual Task<IdentityResult> AddClaimAsync(TKey userId, Claim claim);
        //
        // 摘要:
        //     Associate a login with a user
        //
        // 參數:
        //   userId:
        //
        //   login:
        [AsyncStateMachine(typeof(UserManager<,>.<AddLoginAsync>d__98))]
        public virtual Task<IdentityResult> AddLoginAsync(TKey userId, UserLoginInfo login);
        //
        // 摘要:
        //     Add a user password only if one does not already exist
        //
        // 參數:
        //   userId:
        //
        //   password:
        [AsyncStateMachine(typeof(UserManager<,>.<AddPasswordAsync>d__83))]
        public virtual Task<IdentityResult> AddPasswordAsync(TKey userId, string password);
        //
        // 摘要:
        //     Add a user to a role
        //
        // 參數:
        //   userId:
        //
        //   role:
        [AsyncStateMachine(typeof(UserManager<,>.<AddToRoleAsync>d__105))]
        public virtual Task<IdentityResult> AddToRoleAsync(TKey userId, string role);
        //
        // 摘要:
        //     Method to add user to multiple roles
        //
        // 參數:
        //   userId:
        //     user id
        //
        //   roles:
        //     list of role names
        [AsyncStateMachine(typeof(UserManager<,>.<AddToRolesAsync>d__106))]
        public virtual Task<IdentityResult> AddToRolesAsync(TKey userId, params string[] roles);
        //
        // 摘要:
        //     Change a user password
        //
        // 參數:
        //   userId:
        //
        //   currentPassword:
        //
        //   newPassword:
        [AsyncStateMachine(typeof(UserManager<,>.<ChangePasswordAsync>d__84))]
        public virtual Task<IdentityResult> ChangePasswordAsync(TKey userId, string currentPassword, string newPassword);
        //
        // 摘要:
        //     Set a user's phoneNumber with the verification token
        //
        // 參數:
        //   userId:
        //
        //   phoneNumber:
        //
        //   token:
        [AsyncStateMachine(typeof(UserManager<,>.<ChangePhoneNumberAsync>d__121))]
        public virtual Task<IdentityResult> ChangePhoneNumberAsync(TKey userId, string phoneNumber, string token);
        //
        // 摘要:
        //     Returns true if the password is valid for the user
        //
        // 參數:
        //   user:
        //
        //   password:
        [AsyncStateMachine(typeof(UserManager<,>.<CheckPasswordAsync>d__81))]
        public virtual Task<bool> CheckPasswordAsync(TUser user, string password);
        //
        // 摘要:
        //     Confirm the user's email with confirmation token
        //
        // 參數:
        //   userId:
        //
        //   token:
        [AsyncStateMachine(typeof(UserManager<,>.<ConfirmEmailAsync>d__116))]
        public virtual Task<IdentityResult> ConfirmEmailAsync(TKey userId, string token);
        //
        // 摘要:
        //     Create a user with the given password
        //
        // 參數:
        //   user:
        //
        //   password:
        [AsyncStateMachine(typeof(UserManager<,>.<CreateAsync>d__79))]
        public virtual Task<IdentityResult> CreateAsync(TUser user, string password);
        //
        // 摘要:
        //     Create a user with no password
        //
        // 參數:
        //   user:
        [AsyncStateMachine(typeof(UserManager<,>.<CreateAsync>d__73))]
        public virtual Task<IdentityResult> CreateAsync(TUser user);
        //
        // 摘要:
        //     Creates a ClaimsIdentity representing the user
        //
        // 參數:
        //   user:
        //
        //   authenticationType:
        public virtual Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType);
        //
        // 摘要:
        //     Delete a user
        //
        // 參數:
        //   user:
        [AsyncStateMachine(typeof(UserManager<,>.<DeleteAsync>d__75))]
        public virtual Task<IdentityResult> DeleteAsync(TUser user);
        //
        // 摘要:
        //     Dispose this object
        public void Dispose();
        //
        // 摘要:
        //     Return a user with the specified username and password or null if there is no
        //     match.
        //
        // 參數:
        //   userName:
        //
        //   password:
        [AsyncStateMachine(typeof(UserManager<,>.<FindAsync>d__80))]
        public virtual Task<TUser> FindAsync(string userName, string password);
        //
        // 摘要:
        //     Returns the user associated with this login
        public virtual Task<TUser> FindAsync(UserLoginInfo login);
        //
        // 摘要:
        //     Find a user by his email
        //
        // 參數:
        //   email:
        public virtual Task<TUser> FindByEmailAsync(string email);
        //
        // 摘要:
        //     Find a user by id
        //
        // 參數:
        //   userId:
        public virtual Task<TUser> FindByIdAsync(TKey userId);
        //
        // 摘要:
        //     Find a user by user name
        //
        // 參數:
        //   userName:
        public virtual Task<TUser> FindByNameAsync(string userName);
        //
        // 摘要:
        //     Generate a code that the user can use to change their phone number to a specific
        //     number
        //
        // 參數:
        //   userId:
        //
        //   phoneNumber:
        [AsyncStateMachine(typeof(UserManager<,>.<GenerateChangePhoneNumberTokenAsync>d__124))]
        public virtual Task<string> GenerateChangePhoneNumberTokenAsync(TKey userId, string phoneNumber);
        //
        // 摘要:
        //     Get the email confirmation token for the user
        //
        // 參數:
        //   userId:
        public virtual Task<string> GenerateEmailConfirmationTokenAsync(TKey userId);
        //
        // 摘要:
        //     Generate a password reset token for the user using the UserTokenProvider
        //
        // 參數:
        //   userId:
        public virtual Task<string> GeneratePasswordResetTokenAsync(TKey userId);
        //
        // 摘要:
        //     Get a token for a specific two factor provider
        //
        // 參數:
        //   userId:
        //
        //   twoFactorProvider:
        [AsyncStateMachine(typeof(UserManager<,>.<GenerateTwoFactorTokenAsync>d__131))]
        public virtual Task<string> GenerateTwoFactorTokenAsync(TKey userId, string twoFactorProvider);
        //
        // 摘要:
        //     Get a user token for a specific purpose
        //
        // 參數:
        //   purpose:
        //
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GenerateUserTokenAsync>d__127))]
        public virtual Task<string> GenerateUserTokenAsync(string purpose, TKey userId);
        //
        // 摘要:
        //     Returns the number of failed access attempts for the user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetAccessFailedCountAsync>d__146))]
        public virtual Task<int> GetAccessFailedCountAsync(TKey userId);
        //
        // 摘要:
        //     Get a users's claims
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetClaimsAsync>d__103))]
        public virtual Task<IList<Claim>> GetClaimsAsync(TKey userId);
        //
        // 摘要:
        //     Get a user's email
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetEmailAsync>d__112))]
        public virtual Task<string> GetEmailAsync(TKey userId);
        //
        // 摘要:
        //     Returns whether lockout is enabled for the user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetLockoutEnabledAsync>d__141))]
        public virtual Task<bool> GetLockoutEnabledAsync(TKey userId);
        //
        // 摘要:
        //     Returns when the user is no longer locked out, dates in the past are considered
        //     as not being locked out
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetLockoutEndDateAsync>d__142))]
        public virtual Task<DateTimeOffset> GetLockoutEndDateAsync(TKey userId);
        //
        // 摘要:
        //     Gets the logins for a user.
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetLoginsAsync>d__99))]
        public virtual Task<IList<UserLoginInfo>> GetLoginsAsync(TKey userId);
        //
        // 摘要:
        //     Get a user's phoneNumber
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetPhoneNumberAsync>d__119))]
        public virtual Task<string> GetPhoneNumberAsync(TKey userId);
        //
        // 摘要:
        //     Returns the roles for the user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetRolesAsync>d__109))]
        public virtual Task<IList<string>> GetRolesAsync(TKey userId);
        //
        // 摘要:
        //     Returns the current security stamp for a user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetSecurityStampAsync>d__89))]
        public virtual Task<string> GetSecurityStampAsync(TKey userId);
        //
        // 摘要:
        //     Get whether two factor authentication is enabled for a user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetTwoFactorEnabledAsync>d__134))]
        public virtual Task<bool> GetTwoFactorEnabledAsync(TKey userId);
        //
        // 摘要:
        //     Returns a list of valid two factor providers for a user
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<GetValidTwoFactorProvidersAsync>d__129))]
        public virtual Task<IList<string>> GetValidTwoFactorProvidersAsync(TKey userId);
        //
        // 摘要:
        //     Returns true if the user has a password
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<HasPasswordAsync>d__82))]
        public virtual Task<bool> HasPasswordAsync(TKey userId);
        //
        // 摘要:
        //     Returns true if the user's email has been confirmed
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<IsEmailConfirmedAsync>d__117))]
        public virtual Task<bool> IsEmailConfirmedAsync(TKey userId);
        //
        // 摘要:
        //     Returns true if the user is in the specified role
        //
        // 參數:
        //   userId:
        //
        //   role:
        [AsyncStateMachine(typeof(UserManager<,>.<IsInRoleAsync>d__110))]
        public virtual Task<bool> IsInRoleAsync(TKey userId, string role);
        //
        // 摘要:
        //     Returns true if the user is locked out
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<IsLockedOutAsync>d__139))]
        public virtual Task<bool> IsLockedOutAsync(TKey userId);
        //
        // 摘要:
        //     Returns true if the user's phone number has been confirmed
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<IsPhoneNumberConfirmedAsync>d__122))]
        public virtual Task<bool> IsPhoneNumberConfirmedAsync(TKey userId);
        //
        // 摘要:
        //     Notify a user with a token using a specific two-factor authentication provider's
        //     Notify method
        //
        // 參數:
        //   userId:
        //
        //   twoFactorProvider:
        //
        //   token:
        [AsyncStateMachine(typeof(UserManager<,>.<NotifyTwoFactorTokenAsync>d__132))]
        public virtual Task<IdentityResult> NotifyTwoFactorTokenAsync(TKey userId, string twoFactorProvider, string token);
        //
        // 摘要:
        //     Register a two factor authentication provider with the TwoFactorProviders mapping
        //
        // 參數:
        //   twoFactorProvider:
        //
        //   provider:
        public virtual void RegisterTwoFactorProvider(string twoFactorProvider, IUserTokenProvider<TUser, TKey> provider);
        //
        // 摘要:
        //     Remove a user claim
        //
        // 參數:
        //   userId:
        //
        //   claim:
        [AsyncStateMachine(typeof(UserManager<,>.<RemoveClaimAsync>d__102))]
        public virtual Task<IdentityResult> RemoveClaimAsync(TKey userId, Claim claim);
        //
        // 摘要:
        //     Remove a user from a role.
        //
        // 參數:
        //   userId:
        //
        //   role:
        [AsyncStateMachine(typeof(UserManager<,>.<RemoveFromRoleAsync>d__108))]
        public virtual Task<IdentityResult> RemoveFromRoleAsync(TKey userId, string role);
        //
        // 摘要:
        //     Remove user from multiple roles
        //
        // 參數:
        //   userId:
        //     user id
        //
        //   roles:
        //     list of role names
        [AsyncStateMachine(typeof(UserManager<,>.<RemoveFromRolesAsync>d__107))]
        public virtual Task<IdentityResult> RemoveFromRolesAsync(TKey userId, params string[] roles);
        //
        // 摘要:
        //     Remove a user login
        //
        // 參數:
        //   userId:
        //
        //   login:
        [AsyncStateMachine(typeof(UserManager<,>.<RemoveLoginAsync>d__97))]
        public virtual Task<IdentityResult> RemoveLoginAsync(TKey userId, UserLoginInfo login);
        //
        // 摘要:
        //     Remove a user's password
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<RemovePasswordAsync>d__85))]
        public virtual Task<IdentityResult> RemovePasswordAsync(TKey userId);
        //
        // 摘要:
        //     Resets the access failed count for the user to 0
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<ResetAccessFailedCountAsync>d__145))]
        public virtual Task<IdentityResult> ResetAccessFailedCountAsync(TKey userId);
        //
        // 摘要:
        //     Reset a user's password using a reset password token
        //
        // 參數:
        //   userId:
        //
        //   token:
        //
        //   newPassword:
        [AsyncStateMachine(typeof(UserManager<,>.<ResetPasswordAsync>d__92))]
        public virtual Task<IdentityResult> ResetPasswordAsync(TKey userId, string token, string newPassword);
        //
        // 摘要:
        //     Send an email to the user
        //
        // 參數:
        //   userId:
        //
        //   subject:
        //
        //   body:
        [AsyncStateMachine(typeof(UserManager<,>.<SendEmailAsync>d__136))]
        public virtual Task SendEmailAsync(TKey userId, string subject, string body);
        //
        // 摘要:
        //     Send a user a sms message
        //
        // 參數:
        //   userId:
        //
        //   message:
        [AsyncStateMachine(typeof(UserManager<,>.<SendSmsAsync>d__137))]
        public virtual Task SendSmsAsync(TKey userId, string message);
        //
        // 摘要:
        //     Set a user's email
        //
        // 參數:
        //   userId:
        //
        //   email:
        [AsyncStateMachine(typeof(UserManager<,>.<SetEmailAsync>d__113))]
        public virtual Task<IdentityResult> SetEmailAsync(TKey userId, string email);
        //
        // 摘要:
        //     Sets whether lockout is enabled for this user
        //
        // 參數:
        //   userId:
        //
        //   enabled:
        [AsyncStateMachine(typeof(UserManager<,>.<SetLockoutEnabledAsync>d__140))]
        public virtual Task<IdentityResult> SetLockoutEnabledAsync(TKey userId, bool enabled);
        //
        // 摘要:
        //     Sets the when a user lockout ends
        //
        // 參數:
        //   userId:
        //
        //   lockoutEnd:
        [AsyncStateMachine(typeof(UserManager<,>.<SetLockoutEndDateAsync>d__143))]
        public virtual Task<IdentityResult> SetLockoutEndDateAsync(TKey userId, DateTimeOffset lockoutEnd);
        //
        // 摘要:
        //     Set a user's phoneNumber
        //
        // 參數:
        //   userId:
        //
        //   phoneNumber:
        [AsyncStateMachine(typeof(UserManager<,>.<SetPhoneNumberAsync>d__120))]
        public virtual Task<IdentityResult> SetPhoneNumberAsync(TKey userId, string phoneNumber);
        //
        // 摘要:
        //     Set whether a user has two factor authentication enabled
        //
        // 參數:
        //   userId:
        //
        //   enabled:
        [AsyncStateMachine(typeof(UserManager<,>.<SetTwoFactorEnabledAsync>d__135))]
        public virtual Task<IdentityResult> SetTwoFactorEnabledAsync(TKey userId, bool enabled);
        //
        // 摘要:
        //     Update a user
        //
        // 參數:
        //   user:
        [AsyncStateMachine(typeof(UserManager<,>.<UpdateAsync>d__74))]
        public virtual Task<IdentityResult> UpdateAsync(TUser user);
        //
        // 摘要:
        //     Generate a new security stamp for a user, used for SignOutEverywhere functionality
        //
        // 參數:
        //   userId:
        [AsyncStateMachine(typeof(UserManager<,>.<UpdateSecurityStampAsync>d__90))]
        public virtual Task<IdentityResult> UpdateSecurityStampAsync(TKey userId);
        //
        // 摘要:
        //     Verify the code is valid for a specific user and for a specific phone number
        //
        // 參數:
        //   userId:
        //
        //   token:
        //
        //   phoneNumber:
        [AsyncStateMachine(typeof(UserManager<,>.<VerifyChangePhoneNumberTokenAsync>d__125))]
        public virtual Task<bool> VerifyChangePhoneNumberTokenAsync(TKey userId, string token, string phoneNumber);
        //
        // 摘要:
        //     Verify a two factor token with the specified provider
        //
        // 參數:
        //   userId:
        //
        //   twoFactorProvider:
        //
        //   token:
        [AsyncStateMachine(typeof(UserManager<,>.<VerifyTwoFactorTokenAsync>d__130))]
        public virtual Task<bool> VerifyTwoFactorTokenAsync(TKey userId, string twoFactorProvider, string token);
        //
        // 摘要:
        //     Verify a user token with the specified purpose
        //
        // 參數:
        //   userId:
        //
        //   purpose:
        //
        //   token:
        [AsyncStateMachine(typeof(UserManager<,>.<VerifyUserTokenAsync>d__126))]
        public virtual Task<bool> VerifyUserTokenAsync(TKey userId, string purpose, string token);
        //
        // 摘要:
        //     When disposing, actually dipose the store
        //
        // 參數:
        //   disposing:
        protected virtual void Dispose(bool disposing);
        [AsyncStateMachine(typeof(UserManager<,>.<UpdatePassword>d__86))]
        protected virtual Task<IdentityResult> UpdatePassword(IUserPasswordStore<TUser, TKey> passwordStore, TUser user, string newPassword);
        //
        // 摘要:
        //     By default, retrieves the hashed password from the user store and calls PasswordHasher.VerifyHashPassword
        //
        // 參數:
        //   store:
        //
        //   user:
        //
        //   password:
        [AsyncStateMachine(typeof(UserManager<,>.<VerifyPasswordAsync>d__87))]
        protected virtual Task<bool> VerifyPasswordAsync(IUserPasswordStore<TUser, TKey> store, TUser user, string password);
    }
}



IIdentityMessageService本身就訂好要實作的寄送方法


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#region 組件 Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// D:\SideProjects\AgricultureManagementSystem_Tmp\AgricultureManagementSystem\packages\Microsoft.AspNet.Identity.Core.2.2.3\lib\net45\Microsoft.AspNet.Identity.Core.dll
#endregion

using System.Threading.Tasks;

namespace Microsoft.AspNet.Identity
{
    //
    // 摘要:
    //     Expose a way to send messages (i.e. email/sms)
    public interface IIdentityMessageService
    {
        //
        // 摘要:
        //     This method should send the message
        //
        // 參數:
        //   message:
        Task SendAsync(IdentityMessage message);
    }
}


這邊傳入的 IdentityMessage型別就是Identity框架已經幫我們封裝好
支援手機簡訊跟郵件資訊的DTO

 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
#region 組件 Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// D:\SideProjects\AgricultureManagementSystem_Tmp\AgricultureManagementSystem\packages\Microsoft.AspNet.Identity.Core.2.2.3\lib\net45\Microsoft.AspNet.Identity.Core.dll
#endregion

namespace Microsoft.AspNet.Identity
{
    //
    // 摘要:
    //     Represents a message
    public class IdentityMessage
    {
        public IdentityMessage();

        //
        // 摘要:
        //     Destination, i.e. To email, or SMS phone number
        public virtual string Destination { get; set; }
        //
        // 摘要:
        //     Subject
        public virtual string Subject { get; set; }
        //
        // 摘要:
        //     Message contents
        public virtual string Body { get; set; }
    }
}




這裡準備好一個寄信公用Utility程式



 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
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Web;

namespace AgricultureManagementSystem.Public
{
    public class Common
    {
        public static bool SendMail(string smtpServer, int smtpPort, string password, string strFrom, string strTo, string strSubject, string strBody)
        {
            MailAddress mailFrom = new MailAddress(strFrom);
            MailAddress mailTo = new MailAddress(strTo);

            MailMessage mailMessage = new MailMessage(mailFrom, mailTo)
            {
                Subject = strSubject,
                Body=strBody,
                IsBodyHtml = true                
            };

            SmtpClient smtpClient = new SmtpClient()
            {
                Host = smtpServer,
                Port = smtpPort,
                UseDefaultCredentials = true,
                Credentials = new NetworkCredential(strFrom, password)
            };
            smtpClient.Send(mailMessage);

            mailFrom = null;
            mailTo = null;
            smtpClient.Dispose();
            mailMessage.Dispose();
            return true;
        }


    }
}



在IdentityConfig.cs新增EmailService並於UserManager Create方法裡面進行註冊


 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using AgricultureManagementSystem.Models;
using AgricultureManagementSystem.Public;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;

namespace AgricultureManagementSystem
{
    public class UserManager : UserManager<User>
    {
        public UserManager(IUserStore<User> store) : base(store)
        {

        }

        public static UserManager Create(IdentityFactoryOptions<UserManager> options, IOwinContext context)
        {
            var manager = new UserManager(new UserStore<User>(context.Get<Models.IdentityDbContext>()));
            //manager.UserValidator = new UserValidator<User>(manager)
            //{
            //    AllowOnlyAlphanumericUserNames = false,
            //    RequireUniqueEmail = true
            //};

            manager.UserValidator = new CustomUserValidator(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            manager.EmailService = new EmailService();
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("EmailConfirm"));
            }

            return manager;
        }
    }

    public class EmailService : IIdentityMessageService
    {

        //https://developers.google.com/gmail/imap/imap-smtp
        public Task SendAsync(IdentityMessage message)
        {
            Common.SendMail("smtp.gmail.com", 587, ConfigurationManager.AppSettings["MailPwd"], "chousml@gmail.com", message.Destination, message.Subject, message.Body);
            return Task.FromResult(0);
        }
    }
}




manager.EmailService = new EmailService();

這裡設置我們自建的EmailService class實體

而在IdentityFactoryOptions 中透過DataProtectionProvider
做發信配置到UserManager的過程

在註冊表單Post事件Add增加發註冊驗證信的程式
以及用戶點擊信件連結觸發驗證信箱的方法

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Add(AddUserViewModel addUserViewModel)
{
    if (ModelState.IsValid)
    {
        var user = new User
        {
            UserName = addUserViewModel.Account,
            Account = addUserViewModel.Account,
            Email = addUserViewModel.Email,
            Region = addUserViewModel.Region
        };

        var result = await UserManager.CreateAsync(user, addUserViewModel.Password);
        if (result.Succeeded)
        {
            string verify_code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
            //string verify_code_encode = HttpUtility.UrlEncode(verify_code);
            var verify_EmailUrl = Url.Action("ConfirmEmail", "Register", new { userId = user.Id, code = verify_code }, protocol: Request.Url.Scheme);
            await UserManager.SendEmailAsync(user.Id, "新註冊用戶信箱開通", "請點擊如下連結 <a href =\"" + verify_EmailUrl + "\">Here</a>來確認你的帳戶");
            return RedirectToAction("Index", "Login");
        }
        AddErrors(result);
    }

    //return RedirectToAction("Index", "Register", addUserViewModel);
    return View(addUserViewModel);
}

[HttpGet]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(code))
    {
        return View("Error");
    }

    var result = await UserManager.ConfirmEmailAsync(userId, code);
    
    return View(result.Succeeded ? "ConfirmEmail" : "Error");
}


當成功驗證回傳後就會將AspNetUsers表中的
[EmailConfirmed]更新為true





在記得擴充兩個檢視顯示
錯誤警示的和信箱成功啟用的檢視






#################更新#################

針對Identity 若有去客自訂自己客製化額外跟DB查檢的部分若寫在自己覆寫的

要小心Identity本身封裝的method執行生命週期只要跑到
CreateAsync
UpdateAsync
ConfirmEmailAsync
.....

都會再跑進UserValidator包含自己overwrite的衍生Class中的
public override async Task<IdentityResult> ValidateAsync(User user)方法







#################更新#################


Ref:
[WEB API] Identity 寄Email驗證帳號和密碼規則
https://dotblogs.com.tw/kinanson/2015/05/13/151271

[WEB API]Identity 實現登入Token驗証
https://dotblogs.com.tw/kinanson/2015/05/17/151323



留言

這個網誌中的熱門文章

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

經得起原始碼資安弱點掃描的程式設計習慣培養(三)_7.Cross Site Scripting(XSS)_Stored XSS_Reflected XSS All Clients

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題