.net core identity 集成 github (一)

首先 nuget 需要引用相关的包

EF

Microsoft.EntityFrameworkCore

Microsoft.EntityFrameworkCore.Tools

Microsoft.EntityFrameworkCore.SqlServer

Microsoft.EntityFrameworkCore.Design

支持延迟加载

Microsoft.EntityFrameworkCore.Proxies

 

Identity

Microsoft.AspNetCore.Identity

Microsoft.AspNetCore.Identity.EntityFrameworkCore

集成GitHub

AspNet.Security.OAuth.GitHub

配置GitHub 应用 ClientID ClientSecrets

登录GitHub

 

 

 

 按自己的需要配置

 

配置完 就有 ClientID ClientSecrets

 

appsettings.json GitHub配置

1   "Authentication": {
2     "GitHub": {
3       "AppID": "你的ID",
4       "ClientID": "你的ClientID",
5       "ClientSecrets": "你的ClientSecrets"
6 
7     },

核心代码

 1 //身份验证配置
 2 builder.Services.AddAuthentication(options =>
 3 {
 4     //cookie解决方案
 5     options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
 6 
 7 }).AddCookie(options =>
 8 {
 9     //过期时间 60分钟
10     options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
11     //开启滑动过期
12     options.SlidingExpiration = true;
13 }).AddGitHub(options =>
14 {
15     //集成GitHub
16     options.ClientId = builder.Configuration["Authentication:GitHub:ClientID"];
17     options.ClientSecret = builder.Configuration["Authentication:GitHub:ClientSecrets"];
18     //读取 email 默认没有设置读取不到
19     options.Scope.Add("user:email");
20 });
21 //数据库设置和注入
22 builder.Services.AddDbContext<ShopAppContext>(options =>
23 {
24     string con = builder.Configuration.GetConnectionString("con");
25     options.UseLazyLoadingProxies();
26     options.UseSqlServer(con);
27 });
28 //identity设置
29 builder.Services.Configure<IdentityOptions>(options =>
30 {
31     //最多失误次数锁定
32     options.Lockout.MaxFailedAccessAttempts = 5;
33     //每次锁定15分钟
34     options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
35     //登陆必须是邮件确认的
36     options.SignIn.RequireConfirmedEmail = true;
37 
38     //自定义邮箱token生成提供程序
39     options.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
40 
41     //密码设置
42     options.Password.RequiredLength = 6;
43     options.Password.RequiredUniqueChars = 3;
44     options.Password.RequireNonAlphanumeric = false;
45     options.Password.RequireLowercase = false;
46     options.Password.RequireUppercase = false;
47     options.Password.RequireDigit = false;
48 
49 });
50 //identity注入
51 builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
52     .AddErrorDescriber<CustomIdentityErrorDescriber>()
53     .AddEntityFrameworkStores<ShopAppContext>()
54     .AddDefaultTokenProviders()
55   //  .AddTokenProvider<CustomEmailConfirmationTokenProvider<ApplicationUser>>("CustomEmailConfirmation")
56     ;

 

AccountController 

  1  public class AccountController : Controller
  2     {
  3         private readonly SignInManager<ApplicationUser> _signInManager;
  4         private readonly UserManager<ApplicationUser> _userManager;
  5         private readonly ILogger<AccountController> _logger;
  6         public AccountController(UserManager<ApplicationUser> userManager,
  7             SignInManager<ApplicationUser> signInManager,
  8             ILogger<AccountController> logger)
  9         {
 10             _userManager = userManager;
 11             _signInManager = signInManager;
 12             _logger = logger;
 13         }
 14 
 15         [HttpGet]
 16         public IActionResult Register()
 17         {
 18             return View();
 19         }
 20 
 21 
 22         [HttpPost]
 23         public async Task<IActionResult> RegisterAsync(RegisterViewModel viewModel)
 24         {
 25             if (ModelState.IsValid)
 26             {
 27                 ApplicationUser user = await this._userManager.FindByNameAsync(viewModel.Email);
 28                 if (user != null)
 29                 {
 30                     ModelState.AddModelError("error", $"Email:{viewModel.Email},已注册!");
 31                     return View();
 32                 }
 33                 else
 34                 {
 35                     user = new ApplicationUser
 36                     {
 37                         UserName = viewModel.Email,
 38                         Email = viewModel.Email,
 39                     };
 40                     var result = await _userManager.CreateAsync(user, viewModel.Password);
 41                     if (result.Succeeded)
 42                     {
 43 
 44                         string token = await this._userManager.GenerateEmailConfirmationTokenAsync(user);
 45                         string confirmEmailLink = Url.Action("ConfirmEmail", "Account", new { userID = user.Id, token = token }, Request.Scheme);
 46                         this._logger.Log(LogLevel.Error, confirmEmailLink);
 47                         ViewBag.ErrorTitle = "注册成功";
 48                         ViewBag.ErrorMessage = $"在你登入系统前,我们已经给您发了一份邮件,需要您先进行邮件验证,点击确认链接即可完成。";
 49                         return View("Error");
 50                         //await _signInManager.SignInAsync(user, isPersistent: false);
 51                         //bool s = _signInManager.IsSignedIn(User);
 52                         //return RedirectToAction("Index", "Home");
 53                     }
 54                     foreach (var error in result.Errors)
 55                     {
 56                         ModelState.AddModelError("error", error.Description);
 57                     }
 58                 }
 59             }
 60             return View();
 61         }
 62 
 63 
 64 
 65 
 66         [HttpGet]
 67         public async Task<IActionResult> LogoutAsync()
 68         {
 69             await _signInManager.SignOutAsync();
 70             return RedirectToAction("Index", "Home");
 71         }
 72 
 73 
 74         [HttpGet]
 75         public async Task<IActionResult> LoginAsync(string ReturlUrl)
 76         {
 77             LoginViewModel loginViewModel = new LoginViewModel
 78             {
 79                 ReturnUrl = ReturlUrl,
 80                 ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
 81             };
 82 
 83             return View(loginViewModel);
 84         }
 85 
 86 
 87         //[HttpPost]
 88         //public async Task<IActionResult> LoginAsync(LoginViewModel viewModel)
 89         //{
 90         //    if (ModelState.IsValid)
 91         //    {
 92         //        var result = await _signInManager.PasswordSignInAsync(viewModel.Email, viewModel.Password, viewModel.RememberMe, true);
 93         //        if (result.Succeeded)
 94         //        {
 95         //            return RedirectToAction("Index", "Home");
 96         //        }
 97         //        else
 98         //        {
 99         //            ModelState.AddModelError("error", "登录失败请重试");
100         //        }
101         //    }
102         //    return View(viewModel);
103         //}
104 
105         [HttpPost]
106         [AllowAnonymous]
107         public async Task<IActionResult> LoginAsync(LoginViewModel viewModel, string? ReturlUrl)
108         {
109             viewModel.ExternalLogins = (await this._signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
110             if (ModelState.IsValid)
111             {
112                 ApplicationUser applicationUser = new ApplicationUser
113                 {
114                     UserName = viewModel.Email,
115                     Email = viewModel.Email,
116                 };
117                 ApplicationUser resultUser = await this._userManager.FindByEmailAsync(viewModel.Email);
118                 bool checkPasswordResult = await this._userManager.CheckPasswordAsync(applicationUser, viewModel.Password);
119                 //1:通过邮箱查找的用户不能为空2:验证密码用户是否存在3:邮箱是否确认
120                 if (resultUser != null && !resultUser.EmailConfirmed && checkPasswordResult)
121                 {
122                     ModelState.AddModelError("error", "邮箱未确认");
123                     return View(viewModel);
124                 }
125                 //开启锁定
126                 var signInResult = await this._signInManager.PasswordSignInAsync(resultUser,
127                     viewModel.Password,
128                      viewModel.RememberMe, true);
129                 if (signInResult.Succeeded)
130                 {
131                     if (!string.IsNullOrEmpty(ReturlUrl))
132                     {
133                         LocalRedirect(ReturlUrl);
134                     }
135                     else
136                     {
137                         return RedirectToAction("Index", "Home");
138                     }
139                 }
140 
141 
142 
143                 //如果用户已经锁定了
144                 if (signInResult.IsLockedOut)
145                 {
146                     return View("AccountLocked");
147                 }
148 
149 
150                 ModelState.AddModelError("error", "登陆失败");
151             }
152             return View(viewModel);
153         }
154 
155 
156         /// <summary>
157         /// 外部登录
158         /// </summary>
159         /// <param name="provider"></param>
160         /// <param name="returnUrl"></param>
161         /// <returns></returns>
162         [HttpPost]
163         public IActionResult ExternalLogin(string provider, string returnUrl)
164         {
165             var redirectUrl = Url.Action("ExternalLoginCallback", "Account",
166                                 new { ReturnUrl = returnUrl });
167             var properties = _signInManager
168                 .ConfigureExternalAuthenticationProperties(provider, redirectUrl);
169             return new ChallengeResult(provider, properties);
170         }
171 
172         /// <summary>
173         /// 外部登录回调
174         /// </summary>
175         /// <param name="returnUrl"></param>
176         /// <param name="remoteError"></param>
177         /// <returns></returns>
178     /*    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
179         {
180             returnUrl = returnUrl ?? Url.Content("~/");
181             LoginViewModel loginViewModel = new LoginViewModel
182             {
183                 ReturnUrl = returnUrl,
184                 ExternalLogins = (await this._signInManager.GetExternalAuthenticationSchemesAsync()).ToList()
185             };
186             ExternalLoginInfo info = await this._signInManager.GetExternalLoginInfoAsync();
187             //获取第三方用户的邮箱
188             string email = info.Principal.FindFirstValue(ClaimTypes.Email);
189             if (!string.IsNullOrEmpty(email))
190             {
191 
192                 //查找第三方用户的邮箱 本地数据库中是否有该用户
193                 ApplicationUser user = await this._userManager.FindByEmailAsync(email);
194                 //如果该用户邮箱没有确认
195                 if (user != null && !user.EmailConfirmed)
196                 //if (user != null)
197                 {
198                     ModelState.AddModelError(string.Empty, "您的电子邮箱还未进行验证。");
199                     return View("Login", loginViewModel);
200                 }
201             }
202             var signResult = await this._signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false, bypassTwoFactor: true);
203             if (signResult.Succeeded)
204             {
205                 //如果登录了就不用创建用户 直接跳转
206                 return LocalRedirect(returnUrl);
207             }
208             else
209             {             
210                 ApplicationUser applicationUser = new ApplicationUser
211                 {
212                     UserName = info.Principal.FindFirstValue(ClaimTypes.Email),
213                     Email = info.Principal.FindFirstValue(ClaimTypes.Email)
214                 };
215                 var createResult = await this._userManager.CreateAsync(applicationUser);
216                 if (createResult.Succeeded)
217                 {
218                     await this._userManager.AddLoginAsync(applicationUser, info);
219                     await this._signInManager.SignInAsync(applicationUser, isPersistent: false);
220                 }
221                 return RedirectToAction("Index", "Home");
222             }
223             ViewBag.ErrorTitle = $"我们无法从提供商:{info.LoginProvider}中解析到您的邮件地址 ";
224             ViewBag.ErrorMessage = "请通过联系 ltm@ddxc.org 寻求技术支持。";
225             return View("Error");
226         }
227 */
228 
229 
230         /// <summary>
231         /// 外部登录回调
232         /// </summary>
233         /// <param name="returnUrl"></param>
234         /// <param name="remoteError"></param>
235         /// <returns></returns>
236         public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
237         {
238             returnUrl = returnUrl ?? Url.Content("~/");
239             var externalInfo = await this._signInManager.GetExternalLoginInfoAsync();
240             string externalEmail = externalInfo.Principal.FindFirstValue(ClaimTypes.Email);
241             ApplicationUser applicationUser = null;
242             if (externalEmail != null)
243             {
244                 //如果 第三方邮箱不等于空 我要判断该邮箱在本地是否确认过
245                 applicationUser = await this._userManager.FindByEmailAsync(externalEmail);
246                 if (applicationUser != null && !applicationUser.EmailConfirmed)
247                 {
248                     //用户不等于空 并且邮箱没有确认
249                     ModelState.AddModelError(string.Empty, "您的电子邮箱还未进行验证。");
250                     LoginViewModel loginViewModel = new LoginViewModel
251                     {
252                         ExternalLogins = (await this._signInManager.GetExternalAuthenticationSchemesAsync()).ToList(),
253                         ReturnUrl = returnUrl
254                     };
255                     return View("Login", loginViewModel);
256                 }
257             }
258             //如果邮箱确认过 我需要判断 该用户否有已经登陆
259             var externalLoginSignResult = await this._signInManager
260                 .ExternalLoginSignInAsync(externalInfo.LoginProvider,
261                 externalInfo.ProviderKey, false, true);
262             if (externalLoginSignResult.Succeeded)
263             {
264                 return LocalRedirect(returnUrl);
265             }
266             else
267             {
268                 if (externalEmail != null)
269                 {
270                     if (applicationUser == null)
271                     {
272                         applicationUser = new ApplicationUser
273                         {
274                             UserName = externalInfo.Principal.FindFirstValue(ClaimTypes.Email),
275                             Email = externalInfo.Principal.FindFirstValue(ClaimTypes.Email),
276                         };
277                         await this._userManager.CreateAsync(applicationUser);
278                         string token = await this._userManager.GenerateEmailConfirmationTokenAsync(applicationUser);
279                         
280                         string confirmationLink = Url.Action("ConfirmEmail", "Account",
281                              new { userID = applicationUser.Id, token = token }, Request.Scheme);
282                         _logger.Log(LogLevel.Warning, confirmationLink);
283                         ViewBag.ErrorTitle = "注册成功";
284                         ViewBag.ErrorMessage = $"在你登入系统前,我们已经给您发了一份邮件,需要您先进行邮件验证,点击确认链接即可完成。";
285                         return View("Error");
286                     }
287 
288                     //如果 applicationUser 不等于空 我就直接登陆
289                     await this._userManager.AddLoginAsync(applicationUser, externalInfo);
290                     await this._signInManager.SignInAsync(applicationUser, false);
291                     return LocalRedirect(returnUrl);
292                 }
293                 // 如果我们获取不到电子邮件地址,我们需要将请求重定向到错误视图中。
294                 ViewBag.ErrorTitle = $"我们无法从提供商:{externalInfo.LoginProvider}中解析到您的邮件地址 ";
295                 ViewBag.ErrorMessage = "请通过联系 ltm@ddxc.org 寻求技术支持。";
296                 return View("Error");
297             }
298 
299         }
300 
301 
302         /// <summary>
303         /// 确认邮件
304         /// </summary>
305         /// <param name="userID"></param>
306         /// <param name="token"></param>
307         /// <returns></returns>
308         [HttpGet]
309         public async Task<IActionResult> ConfirmEmailAsync(string userID, string token)
310         {
311             if (string.IsNullOrEmpty(userID) && string.IsNullOrEmpty(token))
312             {
313                 return RedirectToAction("Index", "Home");
314             }
315 
316             var user = await this._userManager.FindByIdAsync(userID);
317             if (user == null)
318             {
319                 ViewBag.ErrorTitle = $"当前id{userID}无效";
320                 ViewBag.ErrorMessage = "请通过联系 ltm@ddxc.org 寻求技术支持。";
321                 return View("Error");
322             }
323 
324             var result = await this._userManager.ConfirmEmailAsync(user, token);
325             if (result.Succeeded)
326             {
327                 return View();
328             }
329             else
330             {
331                 ViewBag.ErrorTitle = $"邮箱验证失败";
332                 ViewBag.ErrorMessage = $"邮箱验证失败";
333                 return View("Error");
334             }
335         }
336 
337 
338 
339         /// <summary>
340         /// 拒绝访问
341         /// </summary>
342         /// <param name="ReturnUrl"></param>
343         /// <returns></returns>
344         [HttpGet]
345         public IActionResult AccessDenied(string ReturnUrl)
346         {
347             //防止开放式攻击
348             if (!string.IsNullOrEmpty(ReturnUrl) && Url.IsLocalUrl(ReturnUrl))
349             {
350                 if (ReturnUrl.Contains("Back"))
351                 {
352                     return RedirectToAction("Index", "Home");
353                 }
354                 else
355                 {
356                     return Redirect(ReturnUrl);
357                 }
358             }
359             else
360             {
361                 return RedirectToAction("Index", "Home");
362             }
363         }
364 
365 
366         #region 激活用户
367         [HttpGet]
368         public IActionResult ActivateUserEmail()
369         {
370             return View();
371         }
372 
373 
374         [HttpPost]
375         public async Task<IActionResult> ActivateUserEmail(EmailAddressViewModel emailAddress)
376         {
377             if (ModelState.IsValid)
378             {
379                 var user = await this._userManager.FindByEmailAsync(emailAddress.Email);
380                 if (user != null)
381                 {
382                     bool isConfirmedResult = await this._userManager.IsEmailConfirmedAsync(user);
383                     if (!isConfirmedResult)
384                     {
385                         string token = await this._userManager.GenerateEmailConfirmationTokenAsync(user);
386 
387                         string urlStr = Url.Action("ConfirmEmail", "Acccount", new { userID = user.Id, token = token }, Request.Scheme);
388 
389                         ViewBag.Message = "如果你在我们系统有注册账户,我们已经发了邮件到您的邮箱中,请前往邮箱激活您的用户。";
390                         //重定向用户到忘记密码确认视图
391                         return View("ActivateUserEmailConfirmation", ViewBag.Message);
392                     }
393                 }
394             }
395 
396             ViewBag.Message = "请确认邮箱是否存在异常,现在我们无法给您发送激活链接。";
397             // 为了避免帐户枚举和暴力攻击,所以不进行用户不存在或邮箱未验证的提示
398             return View("ActivateUserEmailConfirmation", ViewBag.Message);
399         }
400         #endregion
401 
402         #region 忘记密码功能 
403 
404         [HttpGet]
405 
406         public IActionResult ForgotPassword()
407         {
408             return View();
409         }
410 
411         [HttpPost]
412 
413         public async Task<IActionResult> ForgotPassword(EmailAddressViewModel emailAddress)
414         {
415             if (ModelState.IsValid)
416             {
417                 var user = await this._userManager.FindByEmailAsync(emailAddress.Email);
418                 if (user != null && user.EmailConfirmed)
419                 {
420                     string token = await this._userManager.GeneratePasswordResetTokenAsync(user);
421                     string passwordResetLink = Url.Action("ResetPassword", "Acccount", new { userID = user.Id, token = token }, Request.Scheme);
422                     // 将密码重置链接记录到文件中
423                     _logger.Log(LogLevel.Warning, passwordResetLink);
424 
425                     //重定向用户到忘记密码确认视图
426                     return View("ForgotPasswordConfirmation");
427                 }
428                 // 为了避免帐户枚举和暴力攻击,所以不进行用户不存在或邮箱未验证的提示
429                 return View("ForgotPasswordConfirmation");
430             }
431             return View(emailAddress);
432         }
433 
434 
435         [HttpGet]
436         public IActionResult ResetPassword(string token, string email)
437         {
438 
439             //如果密码重置令牌或电子邮件为空,则有可能是用户在试图篡改密码重置链接
440             if (token == null || email == null)
441             {
442                 ModelState.AddModelError("", "无效的密码重置令牌");
443             }
444             return View();
445         }
446         [HttpPost]
447         public async Task<IActionResult> ResetPassword(ResetPasswordViewModel viewModel)
448         {
449 
450             if (ModelState.IsValid)
451             {
452                 var user = await this._userManager.FindByEmailAsync(viewModel.Email);
453                 if (user != null)
454                 {
455                     var result = await this._userManager.ResetPasswordAsync(user, viewModel.Token, viewModel.ConfirmPassword);
456 
457                     if (result.Succeeded)
458                     {
459                         if (await this._userManager.IsLockedOutAsync(user))
460                         {
461                             //重置 锁定时间
462                             await this._userManager.SetLockoutEndDateAsync(user, DateTime.UtcNow);
463                             //重置 锁定次数
464                             await this._userManager.ResetAccessFailedCountAsync(user);
465                         }
466                         return View("ResetPasswordConfirmation");
467                     }
468                     //显示验证错误信息。触发行为,当密码重置令牌已用,或密码复杂性规则不符合标准时
469                     foreach (var error in result.Errors)
470                     {
471                         ModelState.AddModelError("", error.Description);
472                     }
473                     return View(viewModel);
474                 }
475                 // 为了避免帐户枚举和暴力攻击,不要提示用户不存在               
476                 return View("ResetPasswordConfirmation");
477             }
478 
479 
480             return View(viewModel);
481         }
482 
483 
484         #endregion
485     }

 

Login.cshtml 视图

 1 @using Shop.ViewModels
 2 @model LoginViewModel
 3 <h4>登录</h4>
 4 <form class="form-horizontal" method="post">
 5     <div class="alert" asp-validation-summary="All"></div>
 6     <div class="control-group">
 7         <label class="control-label" asp-for="Email">邮箱</label>
 8         <div class="controls">
 9             <input type="text" asp-for="Email" placeholder="Email">
10         </div>
11     </div>
12     <div class="control-group">
13         <label class="control-label" asp-for="Password">密码</label>
14         <div class="controls">
15             <input type="password" asp-for="Password" placeholder="Password">
16         </div>
17     </div>
18     <div class="control-group">
19         <div class="controls">
20             <label class="checkbox">
21                 <input type="checkbox" asp-for="RememberMe">记住我
22             </label>
23             <button type="submit" class="btn">登录</button>
24         </div>
25     </div>
26 </form>
27 
28 <div class="col-md-6 border-left ">
29     <h1>扩展登录</h1><hr />
30     <form class="mt-3" method="post" asp-action="ExternalLogin" asp-controller="Account" asp-route-returnUrl="@Model.ReturnUrl">
31         <div>
32 
33             @foreach (var provider in Model.ExternalLogins)
34             {
35                 <button type="submit" class="btn btn-info"
36                     name="provider" value="@provider.Name"
37                     title="Log in using your @provider.DisplayName account">
38                     @provider.DisplayName
39                 </button>
40             }
41         </div>
42     </form>
43 </div>
View Code

Register.cshtml 视图

 1 @using Shop.ViewModels
 2 @model RegisterViewModel
 3 @{
 4     ViewBag.Title = "注册";
 5 }
 6 
 7 
 8 <h1>用户注册</h1>
 9 
10 <div class="row">
11     <div class="col-md-12">
12         <form method="post">
13             <div asp-validation-summary="All" class="text-danger"></div>
14             <div class="form-group">
15                 <label asp-for="Email"></label>
16                 <input asp-for="Email" class="form-control" />
17                 <span asp-validation-for="Email" class="text-danger"></span>
18             </div>
19             <div class="form-group">
20                 <label asp-for="Password"></label>
21                 <input asp-for="Password" class="form-control" />
22                 <span asp-validation-for="Password" class="text-danger"></span>
23             </div>
24             <div class="form-group">
25                 <label asp-for="ConfirmPassword"></label>
26                 <input asp-for="ConfirmPassword" class="form-control" />
27                 <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
28             </div>
29             <button type="submit" class="btn btn-primary">注册</button>
30         </form>
31     </div>
32 </div>
View Code

ResetPassword.cshtml 视图

 1 @using Shop.ViewModels
 2 @model ResetPasswordViewModel
 3 
 4 <h2>重置密码</h2>
 5 <hr />
 6 <div class="row">
 7     <div class="col-md-12">
 8         <form method="post">
 9             <div asp-validation-summary="All" class="text-danger"></div>
10             <input asp-for="Token" type="hidden" />
11             <input asp-for="Email" type="hidden" />
12             <div class="form-group">
13                 <label asp-for="Password"></label>
14                 <input asp-for="Password" class="form-control" />
15                 <span asp-validation-for="Password" class="text-danger"></span>
16             </div>
17             <div class="form-group">
18                 <label asp-for="ConfirmPassword"></label>
19                 <input asp-for="ConfirmPassword" class="form-control" />
20                 <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
21             </div>
22             <button type="submit" class="btn btn-primary">重置</button>
23         </form>
24     </div>
25 </div>
View Code

ResetPasswordConfirmation.cshtml 视图

 1 @using Shop.ViewModels
 2 @model ResetPasswordViewModel
 3 
 4 <h2>重置密码</h2>
 5 <hr />
 6 <div class="row">
 7     <div class="col-md-12">
 8         <form method="post">
 9             <div asp-validation-summary="All" class="text-danger"></div>
10             <input asp-for="Token" type="hidden" />
11             <input asp-for="Email" type="hidden" />
12             <div class="form-group">
13                 <label asp-for="Password"></label>
14                 <input asp-for="Password" class="form-control" />
15                 <span asp-validation-for="Password" class="text-danger"></span>
16             </div>
17             <div class="form-group">
18                 <label asp-for="ConfirmPassword"></label>
19                 <input asp-for="ConfirmPassword" class="form-control" />
20                 <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
21             </div>
22             <button type="submit" class="btn btn-primary">重置</button>
23         </form>
24     </div>
25 </div>
View Code

AccountLocked.cshtml 视图

1 <label class="error">账户被锁定</label>
2 
3 <a asp-action="ForgotPassword" asp-controller="Account">点击重置密码</a>
View Code

ActivateUserEmail.cshtml 视图

 1 @using Shop.ViewModels
 2 @model EmailAddressViewModel
 3 
 4 <h2>激活邮箱</h2>
 5 <hr />
 6 <div class="row">
 7     <div class="col-md-12">
 8         <form method="post">
 9             <div asp-validation-summary="All" class="text-danger"></div>
10             <div class="form-group">
11                 <label asp-for="Email"></label>
12                 <input asp-for="Email" class="form-control" />
13                 <span asp-validation-for="Email" class="text-danger"></span>
14             </div>
15             <button type="submit" class="btn btn-primary">提交</button>
16         </form>
17     </div>
18 </div>
View Code

ActivateUserEmailConfirmation.cshtml 视图

1 <h1 class="text-info">邮件发送通知</h1>
2 <h4 class="text-secondary">
3     @ViewBag.Message
4 
5 </h4>
View Code

ForgotPassword.cshtml 视图 这个没写

1 @{
2 }
View Code

 

测试

 

 

 

 邮箱验证

 

 验证成功集成github用户

 

posted on 2023-03-26 20:20  是水饺不是水饺  阅读(274)  评论(0)    收藏  举报

导航