ASP.NET 标识简介

ASP.NET 成员身份系统于 2005 年引入 ASP.NET 2.0,此后 Web 应用程序通常处理身份验证和授权的方式发生了许多变化。 为 Web、手机或平板电脑生成现代应用程序时,ASP.NET 标识是成员身份系统应有形态的全新视角。

建议使用最安全的身份验证选项。 有关部署到 Azure 的 .NET 应用,请参阅:

Azure Key Vault 和 .NET Aspire 提供了存储和检索机密的最安全方法。 Azure Key Vault 是一种云服务,用于保护加密密钥和机密,例如证书、连接字符串和密码。 有关 .NET Aspire,请参阅 托管与客户端集成之间的安全通信

避免资源所有者密码凭据授予,因为这:

  • 向客户端公开用户的密码。
  • 存在重大安全风险。
  • 仅当其他身份验证流不可用时,才应使用。

将应用部署到测试服务器时,可以使用环境变量将连接字符串设置为测试数据库服务器。 环境变量通常以纯文本、未加密的文本形式存储。 如果计算机或进程遭到入侵,则不受信任的参与方可以访问环境变量。 建议不要使用环境变量来存储生产连接字符串,因为它不是最安全的方法。

配置数据准则:

  • 切勿将密码或其他敏感数据存储在配置提供程序代码或纯文本配置文件中。
  • 请勿在开发或测试环境中使用生产机密。
  • 指定项目外部的机密,以便无法意外将其提交到源代码存储库。

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

ASP.NET 成员身份

ASP.NET 成员身份 旨在解决 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 提供程序相同的限制。 换句话说,它们是为关系数据库设计的,因此很难自定义配置文件和用户信息。 这些提供程序仍然使用表单身份验证来实现登录和注销功能。

ASP.NET 标识

随着多年来 ASP.NET 会员故事的发展,ASP.NET 团队从客户的反馈中学到了很多东西。

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

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

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

  • 一个 ASP.NET 标识系统

    • ASP.NET 标识可用于所有 ASP.NET 框架,例如 ASP.NET MVC、Web 窗体、网页、Web API 和 SignalR。
    • 生成 Web、手机、存储或混合应用程序时,可以使用 ASP.NET 标识。
  • 轻松插入有关用户的配置文件数据

    • 你可以控制用户和个人资料信息的架构。 例如,在应用程序中注册帐户时,可以轻松使系统能够存储用户输入的出生日期。
  • 持久性控制

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

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

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

    • ASP.NET 标识支持基于声明的身份验证,其中用户的标识表示为一组声明。 声明使开发人员在描述用户标识时能够发挥比角色更大的表现力。 虽然角色成员身份只是布尔值(成员或非成员),但声明可以包含有关用户标识和成员身份的丰富信息。
  • 社交登录服务商

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

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

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

ASP.NET 身份验证入门

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

ASP.NET 标识是使用以下过程实现的。 本文的目的是为您提供 ASP.NET Identity 的概述;您可以按步骤进行,也可以只阅读详细信息。 有关使用 ASP.NET 标识创建应用的更详细说明,包括使用新 API 添加用户、角色和配置文件信息,请参阅本文末尾的“后续步骤”部分。

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

    新 ASP dot Net 项目窗口 的图像

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

    • Microsoft.AspNet.Identity.EntityFramework
      此包具有 ASP.NET 标识的 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 标识和 OWIN Cookie 身份验证是基于声明的系统,框架要求应用为用户生成 ClaimsIdentity。 ClaimsIdentity 包含有关用户的所有声明的信息,例如用户所属的角色。

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

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

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

ASP.NET 标识的组件

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

显示 ASP .Net 标识系统组件的图表

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

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

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

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

后续步骤