ASP.NET Identity 简介

ASP.NET 成员资格系统早在 2005 年就随 ASP.NET 2.0 一起引入,此后 Web 应用程序通常处理身份验证和授权的方式发生了许多变化。 ASP.NET Identity 是当你为 Web、手机或平板电脑构建新式应用程序时,成员资格系统应采用的全新外观。

背景:ASP.NET 中的成员身份

ASP.NET 成员身份

ASP.NET Membership 旨在解决 2005 年常见的网站成员身份要求,其中包括表单身份验证,以及用于用户名、密码和配置文件数据的SQL Server数据库。 如今,Web 应用程序的数据存储选项范围更广,大多数开发人员希望允许其网站使用社交标识提供者进行身份验证和授权功能。 ASP.NET 成员资格设计的限制使得这种转换变得困难:

  • 数据库架构专为SQL Server设计,你无法更改它。 可以添加配置文件信息,但其他数据会打包到不同的表中,因此,除了通过配置文件提供程序 API 之外,其他方式都难以访问。
  • 使用提供程序系统可以更改后备数据存储,但系统设计时是围绕适用于关系数据库的假设设计的。 可以编写提供程序以在非关系存储机制(如 Azure 存储表)中存储成员身份信息,但随后必须通过编写大量代码和不适用于 NoSQL 数据库的方法的 System.NotImplementedException 异常来绕过关系设计。
  • 由于登录/注销功能基于表单身份验证,因此成员身份系统无法使用 OWIN。 OWIN 包括用于身份验证的中间件组件,包括支持使用外部标识提供者登录, (Microsoft 帐户、Facebook、Google、Twitter) ,以及使用 本地 Active Directory 或 Azure Active Directory 中的组织帐户登录。 OWIN 还包括对 OAuth 2.0、JWT 和 CORS 的支持。

ASP.NET 简单成员身份

ASP.NET 简单的成员身份是作为 ASP.NET 网页的成员资格系统开发的。 它随 WebMatrix 和 Visual Studio 2010 SP1 一起发布。 简单成员身份的目标是使向网页应用程序添加成员身份功能变得容易。

简单成员身份确实可以更轻松地自定义用户配置文件信息,但它仍然与 ASP.NET 成员身份共享其他问题,并且存在一些限制:

  • 很难将成员资格系统数据保存在非关系存储中。
  • 不能将其与 OWIN 一起使用。
  • 它不适用于现有的 ASP.NET 成员资格提供程序,并且无法扩展。

ASP.NET 通用提供程序

开发 ASP.NET 通用提供程序是为了使成员身份信息能够在Microsoft Azure SQL 数据库中保存,并且还与SQL Server Compact合作。 通用提供程序基于 Entity Framework Code First 构建,这意味着通用提供程序可用于将数据保存在 EF 支持的任何存储中。 使用 通用提供程序,数据库架构也被清理了很多。

通用提供程序基于 ASP.NET 成员资格基础结构构建,因此它们仍具有与 SqlMembership 提供程序相同的限制。 也就是说,它们是针对关系数据库设计的,很难自定义配置文件和用户信息。 这些提供程序仍然使用 Forms 身份验证进行登录和注销功能。

ASP.NET 标识

随着 ASP.NET 中的会员情况多年来不断演变,ASP.NET 团队从客户的反馈中学到了很多东西。

用户通过输入他们在自己的应用程序中注册的用户名和密码登录的假设不再有效。 网络变得更加社交化。 用户通过 Facebook、Twitter 和其他社交网站等社交渠道实时相互交互。 开发人员希望用户能够使用其社交标识登录,以便他们可以在其网站上获得丰富的体验。 新式成员身份系统必须启用对身份验证提供程序(如 Facebook、Twitter 等)的基于重定向的登录。

随着 Web 开发的发展,Web 开发模式也在不断发展。 应用程序代码的单元测试成为应用程序开发人员关注的核心问题。 2008 年,ASP.NET 添加了基于模型-视图-控制器 (MVC) 模式的新框架,部分帮助开发人员构建单元可测试 ASP.NET 应用程序。 想要对应用程序逻辑进行单元测试的开发人员也希望能够使用成员身份系统执行此操作。

考虑到 Web 应用程序开发中的这些更改,ASP.NET Identity 的开发目标如下:

  • 一个 ASP.NET 标识系统

    • ASP.NET 标识可用于所有 ASP.NET 框架,例如 ASP.NET MVC、Web Forms、网页、Web API 和 SignalR。
    • ASP.NET 标识可用于构建 Web、电话、应用商店或混合应用程序。
  • 轻松插入有关用户的个人资料数据

    • 你可以控制用户和配置文件信息的架构。 例如,你可以轻松地让系统存储用户在应用程序中注册帐户时输入的出生日期。
  • 持久性控制

    • 默认情况下,ASP.NET 标识系统将所有用户信息存储在数据库中。 ASP.NET 标识使用 Entity Framework Code First 来实现其所有持久性机制。
    • 由于控制数据库架构,因此更改表名或更改主键的数据类型等常见任务非常简单。
    • 可以轻松插入不同的存储机制,例如 SharePoint、Azure 存储表服务、NoSQL 数据库等,而无需引发 System.NotImplementedExceptions 异常。
  • 单元可测试性

    • ASP.NET 标识使 Web 应用程序更易于单元测试。 可以为使用 ASP.NET Identity 的应用程序部分编写单元测试。
  • 角色提供程序

    • 有一个角色提供程序,可用于按角色限制对应用程序部分的访问。 可以轻松创建“管理员”等角色,并将用户添加到角色。
  • 基于声明

    • ASP.NET Identity 支持基于声明的身份验证,其中用户的标识表示为一组声明。 声明使开发人员在描述用户标识方面比角色所允许的要高得多。 虽然角色成员身份只是布尔 (成员或非成员) ,但声明可以包含有关用户标识和成员身份的丰富信息。
  • 社交登录提供程序

    • 可以轻松地将社交登录名(如 Microsoft 帐户、Facebook、Twitter、Google 等)添加到应用程序,并将特定于用户的数据存储在应用程序中。
  • OWIN 集成

    • ASP.NET 身份验证现在基于可在任何基于 OWIN 的主机上使用的 OWIN 中间件。 ASP.NET Identity 不依赖于 System.Web。 它是一个完全合规的 OWIN 框架,可用于任何 OWIN 托管的应用程序。
    • ASP.NET 标识使用 OWIN 身份验证登录/注销网站中的用户。 这意味着应用程序使用 OWIN CookieAuthentication 来生成 Cookie,而不是使用 FormsAuthentication 来生成 Cookie。
  • NuGet 包

    • ASP.NET 标识作为 NuGet 包重新分发,该包安装在 Visual Studio 2017 随附的 ASP.NET MVC、Web Forms 和 Web API 模板中。 可以从 NuGet 库下载此 NuGet 包。
    • 将 ASP.NET Identity 作为 NuGet 包发布可让 ASP.NET 团队更轻松地迭代新功能和 bug 修复,并以敏捷的方式将这些修补程序交付给开发人员。

ASP.NET 标识入门

ASP.NET 标识用于 ASP.NET MVC、Web Forms、Web API 和 SPA 的 Visual Studio 2017 项目模板。 在本演练中,我们将说明项目模板如何使用 ASP.NET Identity 来添加注册、登录和注销用户的功能。

ASP.NET 标识是使用以下过程实现的。 本文旨在简要概述 ASP.NET 标识;可以分步操作,也可以直接阅读详细信息。 有关使用 ASP.NET Identity 创建应用的详细说明,包括使用新 API 添加用户、角色和配置文件信息,请参阅本文末尾的后续步骤部分。

  1. 使用个人帐户创建 ASP.NET MVC 应用程序。 可以在 ASP.NET MVC、Web Forms、Web API、SignalR 等中使用 ASP.NET 标识。在本文中,我们将从 ASP.NET MVC 应用程序开始。

    新的 ASP dot Net 项目窗口的图像

  2. 创建的项目包含以下三个用于 ASP.NET 标识的包。

    • Microsoft.AspNet.Identity.EntityFramework
      此包具有 ASP.NET Identity 的 Entity Framework 实现,它将 ASP.NET 标识数据和架构持久保存为SQL Server。
    • Microsoft.AspNet.Identity.Core
      此包具有 ASP.NET 标识的核心接口。 此包可用于编写面向不同持久性存储(如 Azure 表存储、NoSQL 数据库等)ASP.NET 标识的实现。
    • Microsoft.AspNet.Identity.OWIN
      此包包含用于在 ASP.NET 应用程序中插入具有 ASP.NET Identity 的 OWIN 身份验证的功能。 将登录功能添加到应用程序并调用 OWIN Cookie 身份验证中间件以生成 Cookie 时,会使用此方法。
  3. 创建用户。
    启动应用程序,然后单击“ 注册 ”链接以创建用户。 下图显示了收集用户名和密码的“注册”页。

    创建新帐户的图像

    当用户选择“ 注册 ”按钮时, Register 帐户控制器的操作会通过调用 ASP.NET 标识 API 来创建用户,如下所示:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser() { UserName = model.UserName };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    }
    
  4. 登录。
    如果用户已成功创建,则使用 SignInAsync 方法登录该用户。

     [HttpPost]
     [AllowAnonymous]
     [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                 await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
                        
                 // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
                 // Send an email with this link
                 // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                 // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                 // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
    
                 return RedirectToAction("Index", "Home");
             }
             AddErrors(result);
         }
    
        // If we got this far, something failed, redisplay form
         return View(model);
     }
    

    方法 SignInManager.SignInAsync 生成 ClaimsIdentity。 由于 ASP.NET Identity 和 OWIN Cookie 身份验证是基于声明的系统,框架要求应用为用户生成 ClaimsIdentity。 ClaimsIdentity 包含有关用户的所有声明的信息,例如用户所属的角色。

  5. 注销。
    选择“ 注销” 链接,在帐户控制器中调用“注销”操作。

    // POST: /Account/LogOff
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Index", "Home");
    }
    

    上面突出显示的代码显示了 OWIN AuthenticationManager.SignOut 方法。 这类似于 Web Forms 中 FormsAuthentication 模块使用的 FormsAuthentication.SignOut 方法。

ASP.NET 标识的组件

下图显示了 ASP.NET 标识系统的组件, (选择此 组件或在关系图上将其放大) 。 绿色的包构成 ASP.NET 标识系统。 所有其他包都是在 ASP.NET 应用程序中使用 ASP.NET 标识系统所需的依赖项。

显示 A S P 点 Net 标识系统的组件的关系图

下面是前面未提及的 NuGet 包的简要说明:

  • Microsoft.Owin.Security.Cookies
    中间件,使应用程序能够使用基于 Cookie 的身份验证,类似于 ASP。NET 的表单身份验证。
  • EntityFramework
    实体框架是 Microsoft 推荐用于关系数据库的数据访问技术。

从成员身份迁移到 ASP.NET 标识

我们希望尽快提供有关将使用 ASP.NET 成员身份或简单成员身份的现有应用迁移到新的 ASP.NET 标识系统的指导。

后续步骤