.NET Core Identity Server 4 认证 VS 身份认证

.NET Core Identity Server 4 Authentication VS Identity Authentication

我正在尝试了解在 ASP.NET Core 中进行身份验证的正确方法。我看过几个资源(其中大部分都过时了)。

有些人提供了替代解决方案,说明使用基于云的解决方案,例如 Azure AD,或者使用 IdentityServer4 并托管我自己的令牌服务器。

在旧版本的 .Net 中,一种更简单的身份验证形式是创建自定义原则并在其中存储额外的身份验证用户数据。

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
    string FirstName { get; set; }

    string LastName { get; set; }
}

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }

    public CustomPrincipal(string username)
    {
        this.Identity = new GenericIdentity(username);
    }

    public bool IsInRole(string role)
    {
        return Identity != null && Identity.IsAuthenticated && 
           !string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return FirstName + " " + LastName; } }
}

public class CustomPrincipalSerializedModel
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

然后您会将数据序列化为 cookie,然后 return 返回给客户端。

public void CreateAuthenticationTicket(string username) {     

    var authUser = Repository.Find(u => u.Username == username);  
    CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();

    serializeModel.FirstName = authUser.FirstName;
    serializeModel.LastName = authUser.LastName;
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    string userData = serializer.Serialize(serializeModel);

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,username,DateTime.Now,DateTime.Now.AddHours(8),false,userData);
    string encTicket = FormsAuthentication.Encrypt(authTicket);
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
    Response.Cookies.Add(faCookie);
}

我的问题是:

  1. 我如何才能像在以前版本的 .Net 中完成的那样进行身份验证,旧方法仍然有效还是有更新的版本。

  2. 使用自己的令牌服务器与创建自己的自定义原则的优缺点是什么?

  3. 当使用基于云的解决方案或单独的令牌服务器时,您将如何将其与当前应用程序集成,我的应用程序中是否仍需要用户 table 您将如何关联两个?

  4. 因为有这么多不同的解决方案,我该如何创建一个企业应用程序,允许通过 Gmail/Facebook 登录,同时仍然能够扩展到其他 SSO

  5. 这些技术有哪些简单的实现方式?

TL;DR

IdentityServer = 通过 OAuth 2.0/OpenId-Connect 的令牌加密和验证服务

ASP.NET 身份 = ASP.NET

中的当前身份管理策略

我怎样才能像以前版本的 .Net 中所做的那样进行身份验证,旧的方法仍然有效还是有更新的版本。

我看不出你为什么不能在 ASP.NET Core 中实现旧方法,但总的来说,该策略已被 ASP.NET Identity 取代,而 ASP.NET Identity 是在 ASP.NET 核心中活得很好。

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity

ASP.NET 身份使用像 SQL 服务器这样的后备存储来保存用户信息,如用户名、密码(散列)、电子邮件、phone,并且很容易扩展以保存名字、姓氏或其他任何东西。所以,真的没有理由将用户信息加密到 cookie 中并在客户端和服务器之间来回传递。它支持用户声明、用户令牌、用户角色和外部登录等概念。以下是 ASP.NET 身份中的实体:

  • AspNetUsers
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins(用于链接外部身份提供者,如 Google、AAD)
  • AspNetUserTokens(用于存储用户积累的 access_tokens 和 refresh_tokens 之类的东西)

使用自己的令牌服务器与创建自己的自定义原则的优缺点是什么?

令牌服务器是一个生成包含授权and/or 身份验证信息的简单数据结构的系统。授权通常采用名为 access_token 的令牌。这就是 "keys to the house",可以这么说,让你通过门口进入受保护资源的住所,通常是网络 api。对于身份验证,id_token 包含 user/person 的唯一标识符。虽然将这样的标识符放在 access_token 中很常见,但现在有一个专用协议可以做到这一点:OpenID-Connect.

拥有自己的安全令牌服务 (STS) 的原因是通过加密保护您的信息资产,并控制哪些客户端(应用程序)可以访问这些资源。此外,身份控制标准现在存在于 OpenID-Connect 规范中。 IdentityServer 是 OAuth 2.0 授权服务器与 OpenID-Connect 身份验证服务器相结合的示例。

但是 none 如果您只希望在您的应用程序中有一个用户 table,那么这是必要的。您不需要令牌服务器 - 只需使用 ASP.NET 身份。 ASP.NET 身份将您的用户映射到服务器上的 ClaimsIdentity 对象 - 不需要自定义 IPrincipal class.

当使用基于云的解决方案或单独的令牌服务器时,您将如何将其与当前应用程序集成,我的应用程序中是否仍需要用户 table 您将如何关联两个?

请参阅这些教程以将单独的身份解决方案与应用程序集成: https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html https://auth0.com/docs/quickstart/webapp/aspnet-core

您至少需要两列 table 将用户名映射到外部提供商的用户标识符。这就是 AspNetUserLogins table 在 ASP.NET Identity 中所做的。然而,table 中的行取决于 AspNetUsers 中的用户记录。

ASP.NET Identity 支持外部提供商,例如 Google、Microsoft、Facebook、任何 OpenID-Connect 提供商、Azure AD 都已经存在。 (Google 并且 Microsoft 已经实施了 OpenID-Connect 协议,因此您也不需要他们的自定义集成包,例如 like this one)。此外,ADFS 在 ASP.NET Core Identity 上尚不可用。

请参阅此文档以开始使用 ASP.NET 身份中的外部提供商:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/

因为有这么多不同的解决方案,我该如何创建一个企业应用程序,允许通过 Gmail/Facebook 登录,同时仍然能够扩展到其他 SSO

如上所述,ASP.NET Identity 已经这样做了。创建 "External Providers" table 和数据驱动您的外部登录过程相当容易。因此,当出现新的 "SSO" 时,只需添加一个新行,其中包含提供商的 url、他们提供给您的客户端 ID 和密码等属性。 ASP.NET Identity 已经在 Visual Studio 模板中包含 UI built,但请参阅 Social Login 以获得更酷的按钮。

总结

如果您只需要一个用户 table 具有密码登录功能和用户配置文件,那么 ASP.NET 身份是完美的。无需涉及外部权威。但是,如果有许多应用程序需要访问许多 api,那么一个独立的机构来保护和验证身份和访问令牌是有意义的。 IdentityServer 非常适合,或者请参阅 openiddict-core, or Auth0 了解云解决方案。

抱歉,这没有切中要害,或者介绍性太强。请随时互动,以获得您正在寻找的靶心。

附录:Cookie 身份验证

要使用 cookie 进行简单的身份验证,请按照以下步骤操作。但是,据我所知,不支持自定义声明主体。要达到相同的效果,请使用 ClaimPrincipal 对象的声明列表。

在 Visual Studio 2015/2017 中创建一个新的 ASP.NET Core 1.1 Web 应用程序,在对话框中选择 "No Authentication"。然后添加包:

Microsoft.AspNetCore.Authentication.Cookies

Startup.cs 中的 Configure 方法下放置这个(在 app.UseMvc 之前):

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "MyCookieMiddlewareInstance",
    LoginPath = new PathString("/Controller/Login/"),
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});

然后 build 登录 ui 和 post html 表单到这样的操作方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(String username, String password, String returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // check user's password hash in database
        // retrieve user info

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username),
            new Claim("FirstName", "Alice"),
            new Claim("LastName", "Smith")
        };

        var identity = new ClaimsIdentity(claims, "Password");

        var principal = new ClaimsPrincipal(identity);

        await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);

        return RedirectToLocal(returnUrl);
    }

    ModelState.AddModelError(String.Empty, "Invalid login attempt.");

    return View();
}

HttpContext.User 对象应该有您的自定义声明,并且可以轻松检索 ClaimPrincipal 的列表集合。

我希望这就足够了,因为完整的 Solution/Project 对于 Whosebug post 来说似乎有点多 post。

我一直使用内置的 ASP.NET 身份(以及以前的成员身份)authorisation/authentication,我最近实施了 Auth0 (https://auth0.com) 并推荐将此作为其他尝试。

使用 Identity 实现社交登录并不难,但涉及一些初始设置,有时您在文档中找到的在线步骤并不相同,通常您可以在平台的开发人员部分找到相关帮助您正在尝试为其设置社交登录。 Identity 是旧版 .net framework.What 中旧成员资格功能的替代品 framework.What 我发现边缘用例,例如将您已经拥有的 jwt 令牌传递给网络 api 并不是即使在 pluralsight 上也涵盖了在线示例中的任何地方,我相信您不需要自己的令牌权限来执行此操作,但我还没有找到一个关于如何在 get 或 post 中传递数据的示例不处理自托管服务器。

TL;DR

我真的很想展示一个关于如何正确实施 IdentityServer4 的完整 posting,但我试图将所有文本放入其中,但它超出了 Whosebug 接受的限制,所以我会正确的一些技巧和我学到的东西。

使用令牌服务器与 ASP 身份相比有什么好处?

令牌服务器有很多好处,但并不适合所有人。如果您正在实施类似企业的解决方案,您希望多个客户端能够登录,令牌服务器是您最好的选择,但如果您只是制作一个想要支持外部登录的简单网站,您可以使用 ASP 身份和一些中间件。

Identity Server 4 技巧

与我见过的许多其他框架相比,Identity Server 4 的文档非常详细,但很难从头开始并了解全貌。

我的第一个错误是尝试使用 OAuth 作为身份验证,是的,有很多方法可以这样做,但 OAuth 用于授权而不是身份验证,如果您想使用 OpenIdConnect (OIDC) 进行身份验证

在我的例子中,我想创建一个 javascript 客户端,它连接到网络 api。 我查看了很多解决方案,但最初我尝试使用 webapi 来调用针对 Identity Server 的身份验证,并且只是让该令牌持久存在,因为它已针对服务器进行了验证。该流程可能会起作用,但它有很多缺陷。

当我找到 Javascript 客户端样本时,终于找到了正确的流程,我得到了正确的流程。您的客户登录并设置令牌。然后你让你的网站 api 使用 OIdc 客户端,它将根据 IdentityServer 验证你的访问令牌。

连接到商店和迁移 起初我对迁移有很多误解。我的印象是 运行 迁移在内部从 dll 生成了 SQL,而不是使用您配置的上下文来弄清楚如何创建 SQL.

迁移有两种语法,知道您的计算机使用哪一种很重要:

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

我认为 Migration 之后的参数是名称,我不确定为什么需要名称,ApplicationDbContext 是您要在其中创建的代码优先 DbContext。

迁移使用一些自动魔法从您的启动配置中找到您的连接字符串,我只是假设它使用了来自服务器资源管理器的连接。

如果您有多个项目,请确保将 ApplicationDbContext 设置为启动项目。

实施授权和身份验证时有很多移动部分,希望这 post 对某人有所帮助。完全理解身份验证的最简单方法是拆开他们的示例,将所有内容拼凑在一起,并确保您阅读了文档

ASP.NET Identity - 无论是 Bearer 还是 Basic Authentication,这是一种验证您的应用程序的方式,它为我们提供了现成的代码来执行用户注册、登录、更改密码等等。

现在考虑我们有 10 个不同的应用程序,在所有 10 个应用程序中做同样的事情是不可行的。这种非常脆弱和非常糟糕的做法。

要解决这个问题,我们可以做的是集中我们的身份验证和授权,这样无论何时对此进行任何更改都不会影响我们所有的 10 个应用程序。

身份服务器为您提供了执行相同操作的能力。我们可以创建一个仅用作身份服务的示例 Web 应用程序,它将验证您的用户并提供一些 JWT 访问令牌。