专栏首页Vincent-yuanasp.net core 系列之用户认证(authentication)

asp.net core 系列之用户认证(authentication)

ASP.NET Core 的 identity 是一种需要用户登录的会员系统,用户可以创建一个登录信息存储在 Identity 的的账号,

或者也可以使用第三方登录,支持的第三方登录包括:Facebook, Google, Microsoft Account, and Twitter.

Identity 使用Sql Server 存储用户的姓名,密码等数据,当然你也可以选择其他的存储工具进行存储

这篇教程,将会讲解如何使用Identity进行用户的注册,登录,登出

1.创建一个带认证(authentication)的web应用

  • 文件->新建->项目
  • 选择ASP.NET Core Web 应用程序,命名WebApp1 ,点击确定
  • 然后选择web 应用程序,然后更改身份验证
  • 选择个人用户账号,确定

生成的项目会提供 ASP.NET Core Identity 功能,并且 Identity area 会暴露 下面几个 终端(endpoint):

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Account/Manage

2.迁移

观察生成的代码,发现migration已经生成了,只需要更新到数据库

在nuget 程序控制台中,输入:

Update-Database

直接在vs中的视图,打开sql server 对象管理器,查看数据库效果,确认数据库更新成功:

3.配置 Identity 服务(Identity service)

服务被添加到了StartUp下的 ConfigureServices方法中

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

  //这里对Identity做一些配置
    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.密码配置
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.锁定设置
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.用户设置
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings 缓存设置
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

4.添加 注册,登录,登录功能

  • 在解决方案的项目上,右键添加->新搭建基架的项目
  • 选择标识,添加
  • 然后选择你想添加的项

这里的数据上下文中需要选中一个数据的,注意

之后,会生成相应的一些文件,包括注册,登录,登出

5.现在再看下,生成的代码

注册
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password); //创建账户
  
     if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); //生成邮箱验证码
            var callbackUrl = Url.Page(  //生成验证的回调地址
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",  //发送邮箱验证邮件
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            await _signInManager.SignInAsync(user, isPersistent: false);  //登录
            return LocalRedirect(returnUrl);
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

创建成功后,会直接显示登录状态

登录
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,  //密码登录
            Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)  //登录成功
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)  //两步验证
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)  //锁定
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}
登出
public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();  //登出
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return Page();
            }
        }
登录页面
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
    @if (SignInManager.IsSignedIn(User))
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity"
               asp-page="/Account/Manage/Index"
               title="Manage">Hello@User.Identity.Name!</a>
        </li>
        <li class="nav-item">
            <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                   asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                   method="post">
                <button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
            </form>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
        </li>
    }
</ul>

6.验证Identity

默认的web项目模板允许匿名访问到主页的,为了验证Identity,给Privacy 页面增加 [Authorize]

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebApp1.Pages
{
  [Authorize]
    public class PrivacyModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}

7.运行

测试注册,登录,登出功能

以及认证效果对比(即Privacy页面增加Authrize前后):

加之前:不需要登录,即可访问Privacy页面

加之后:需要登录,才能访问此页面

这里先记录添加Identity操作流程,之后会具体讲解一些功能点

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java之hibernate之helloworld

    2.增加一个lib文件夹,并把 hibernate必须的jar包 和 数据库驱动包 一起复制进去

    Vincent-yuan
  • 设计模式~解释器

    虽然广义的将,解释器不一定要有一个浏览器,但是使用浏览器仍然是最常见的建立解释器的办法。

    Vincent-yuan
  • 编写自己的简单服务器

    这里记录一个类似tomcat的简单服务器的编写过程,帮助了解使用到的主要技术及原理

    Vincent-yuan
  • Python 竟能绘制出如此酷炫的三维图

    通常我们用 Python 绘制的都是二维平面图,但有时也需要绘制三维场景图,比如像下面这样的:

    double
  • 前后端分离实践:基于vue实现网站前台的权限管理

    CodeSheep
  • 【每周一坑】美队盾牌

    大家好,最近更新频率又慢了,【每周一坑】快变成【每两周一坑】了……不过别急,我们正在酝酿一些好玩又实用的内容和活动,很快会陆续奉上。 刚刚加入不久朋友,如果是初...

    Crossin先生
  • JSP/Servlet Web 学习笔记 DayFour —— 实现一个简单的JSP/Servlet交互

        b)JSP页面由表单获取一个开始数字,一个结束数字,交给Servlet打印响应的乘法表。

    Rekent
  • Java中枚举的线程安全性及序列化问题

    要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和class一样,只是一个关键字,他并不是一个类,那么枚举是由...

    一个程序员的成长
  • 论文阅读理解 - Deep Learning of Binary Hash Codes for Fast Image Retrieval

    AIHGF
  • SCF VS Code 实践:备份MySQL数据库至腾讯云COS

    https://cloud.tencent.com/document/product/583/38090

    孤鸿寄语

扫码关注云+社区

领取腾讯云代金券