.NET Core身份服务器4身份验证VS身份身份验证


92

我试图了解在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,并将其返回给客户端。

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. 当使用基于云的解决方案或单独的令牌服务器时,如何将其与当前应用程序集成,我仍将在应用程序中需要一个用户表,如何将两者关联?

  4. 由于存在众多不同的解决方案,我如何创建企业应用程序,以允许通过Gmail / Facebook登录,同时仍能够扩展到其他SSO

  5. 这些技术的一些简单实现是什么?

这个问题范围太广,而且也很基于意见。对于这种格式,可能答案过多,或者好的答案太长。请添加详细信息以缩小答案范围或隔离可以在几段中回答的问题。许多好的问题会根据专家的经验产生某种程度的意见,但是对这个问题的答案往往几乎完全基于观点,而不是事实,参考资料或特定的专业知识。
Nkosi

@Nkosi很抱歉这句话是那样的。我澄清了这一点
约翰尼

Answers:


145

TL; DR

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

ASP.NET身份= ASP.NET中的当前身份管理策略

我怎样才能像以前版本的.Net一样进行身份验证,是否仍然可以使用旧方法或是否有较新版本。

我认为没有理由无法在ASP.NET Core中实现旧方法,但是总的来说,该策略已被ASP.NET Identity取代,并且ASP.NET Identity在ASP.NET Core中仍然有效。

https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/identity

ASP.NET Identity使用诸如SQL Server之类的后备存储来保存用户信息,例如用户名,密码(散列),电子邮件,电话,并可以轻松地扩展以容纳FirstName,LastName或其他名称。因此,实际上没有理由将用户信息加密为cookie并将其从客户端来回传递到服务器。它支持诸如用户声明,用户令牌,用户角色和外部登录之类的概念。这是ASP.NET Identity中的实体:

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

使用您自己的令牌服务器和创建自己的自定义原理的利弊是什么?

令牌服务器将是一个生成包含授权和/或认证信息的简单数据结构的系统。授权通常采用名为access_token的令牌的for 。可以这么说,这就是“房子的钥匙”,它使您可以进入门口,进入通常是Web API的受保护资源的住所。对于身份验证,id_token包含用户/人员的唯一标识符。尽管通常将这样的标识符放在access_token中,但是现在有专用的协议可以这样做:OpenID-Connect

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

但是,如果您只想在应用程序中使用用户表,则不需要这样做。您不需要令牌服务器,只需使用ASP.NET身份。ASP.NET Identity将您的User映射到服务器上的ClaimsIdentity对象-不需要自定义IPrincipal类。

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

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

至少需要一个两列表,将用户名映射到外部提供商的用户标识符。这就是ASP.NET Identity中AspNetUserLogins表的功能。但是,该表中的行取决于AspNetUsers中的User记录。

ASP.NET Identity支持外部提供程序,例如Google,Microsoft,Facebook,任何OpenID-Connect提供程序,Azure AD。(Google和Microsoft已经实现了OpenID-Connect协议,因此您也不需要它们的自定义集成程序包,例如该程序包)。此外,ADFS在ASP.NET Core Identity上尚不可用。

请参阅此文档以开始使用ASP.NET Identity中的外部提供程序:

https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/social/

由于存在众多不同的解决方案,我如何创建企业应用程序,以允许通过Gmail / Facebook登录,同时仍能够扩展到其他SSO

如上所述,ASP.NET Identity已经做到了这一点。创建“外部提供程序”表很容易,数据驱动您的外部登录过程。因此,当出现新的“ SSO”时,只需添加一个新行,其中包含提供者的url,客户端ID和它们提供给您的秘密之类的属性。ASP.NET Identity已经在其中的Visual Studio模板中内置了UI,但有关更酷的按钮,请参见“社交登录”。

概要

如果您只需要具有密码登录功能的用户表和用户配置文件,则ASP.NET Identity非常适合。无需外部机构的参与。但是,如果有许多应用程序需要访问许多api,那么保护和验证身份和访问令牌的独立权限就很有意义。IdentityServer非常适合,请参阅openiddict-coreAuth0以获取云解决方案。

我很抱歉,这没有达到目标或太过入门。请随时进行互动,以找到您想要的靶心。

附录:Cookie身份验证

要使用Cookie进行裸身身份验证,请按照以下步骤操作。但是,据我所知,不支持自定义声明主体。为了获得相同的效果,请使用ClaimPrincipal对象的Claims列表。

在Visual Studio 2015/2017中创建一个新的ASP.NET Core 1.1 Web应用程序,在对话框中选择“无身份验证”。然后添加包:

Microsoft.AspNetCore.Authentication.Cookies

在适当的Configure方法下Startup.cs(在之前app.UseMvc):

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

然后构建一个登录ui并将html表单发布到这样的Action方法中:

[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的List集合。

我希望这足够了,因为对于StackOverflow帖子来说,完整的解决方案/项目似乎有点多。


1
请显示在内核中实现身份验证的示例
johnny

2
ASP.NET Core文档显示了规范的示例:docs.microsoft.com/en-us/aspnet/core/security/authentication/…
travis.js 2017年

如果可以,请发布一个简单的身份验证示例。由于没有链接,因此人们可以访问资源,我将发布有关如何设置IdentityServer4的深入解答
johnny

对于IdentityServer,是否有您要查找的示例:identityserver4.readthedocs.io/en/dev/quickstarts / ...
travis.js

对于ASP.NET Identity,这是否没有示例,或者您所说的内容已过时?docs.microsoft.com/zh-cn/aspnet/core/security/authentication/…– travis.js
2017年

11

TL; DR

我真的很想显示有关如何正确实现IdentityServer4的完整文章,但我尝试将所有文​​本放入其中,但超出了StackOverflow接受的范围,因此我将纠正一些技巧和我学到的东西。

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

令牌服务器虽然有很多好处,但并不适合所有人。如果您要实施类似企业的解决方案,并且希望多个客户端都可以登录,则令牌服务器是最好的选择,但是如果您只是创建一个简单的网站来支持外部登录,则可以使用ASP Identity和一些中间件。

Identity Server 4技巧

与我见过的许多其他框架相比,Identity Server 4的文档记录得很好,但是很难从头开始并看到整个图片。

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

以我为例,我想创建一个JavaScript客户端,该客户端连接到网络api。我研究了很多解决方案,但是最初我尝试使用webapi来针对Identity Server调用身份验证,只是因为该令牌已针对服务器进行了验证,所以该令牌一直存在。该流程可能会起作用,但存在很多缺陷。

最终,当我找到Javascript Client示例时,正确的流程得到了正确的流程。您的客户端登录并设置令牌。然后,让您的Web API使用OIdc客户端,这将验证您是否针对IdentityServer访问令牌。

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

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

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

我认为Migration之后的参数是名称,为什么我不确定需要一个名称,为什么要ApplicationDbContext在其中创建Code-First DbContext。

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

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

实施授权和认证时有很多活动内容,希望这篇文章对某人有所帮助。全面了解身份验证的最简单方法是拆开示例,将所有内容拼凑起来,并确保已阅读文档。


add-migration之后的名称是与您的发行版/更改相关的参考。相同名称将用于添加迁移脚本Up&Down。
杰伊(Jay)

@杰伊感谢您的澄清
约翰尼

Identity Server的配置数据库上下文仍然不如IdentityDbContext。创建自定义实现很痛苦。Identityserver 4现在似乎不太活跃,无法在.core更新之后发布新更新。
杰伊(Jay)

3

ASP。

现在考虑我们有10个不同的应用程序,并且不可能在所有10个应用程序中执行相同的操作。那非常脆弱和非常糟糕的做法。

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

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


2

我一直使用内置的ASP.NET身份(和以前的成员资格)授权/身份验证,最近我已实现Auth0(https://auth0.com),并建议将其作为其他尝试方法。


Auth0 .net核心示例非常快速且易于实现,但是使用所有功能需要大量工作,我已经实现了Auth0,集成了很多功能并且运行良好,但是像所有这些东西一样,它的需求是有点工作和一些挫折感。
Mark Redman

当我完成一项身份验证后,我将在其上发布深入的答案。过去一周,我一直在进行身份验证。而且,没有什么事比应有的
僵硬了

0

使用Identity并不难实现社交登录,但是涉及一些初始设置,有时您在文档中在线找到的步骤并不相同,通常您可以在要设置的平台的“开发人员”部分下找到相关的帮助。的社交登录信息。身份是对.net框架旧版本中旧的成员身份功能的替代。我发现令人惊讶的是,在线示例中的任何地方都没有涉及边缘用例,例如将已经拥有的jwt令牌传递给Web api即使是复数形式,我也可以肯定您不需要自己的令牌颁发机构来执行此操作,但是我还没有找到一个单独的示例来说明如何在与自托管服务器无关的get或post中传递数据。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.