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

时间:2017-02-08 19:21:48

标签: c# asp.net authentication asp.net-core openid-connect

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

有些人提供了使用基于云的解决方案(如Azure AD)或使用IdentityServer4并托管我自己的令牌服务器的解决方案。

在早期版本的.Net中,一种较简单的身份验证形式是创建自定义Iprinciple并在其中存储其他身份验证用户数据。

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

    < / LI>
  4. 由于有这么多不同的解决方案,我如何创建企业应用程序,允许通过Gmail / Facebook登录,同时仍然可以扩展到其他SSO

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

5 个答案:

答案 0 :(得分:99)

<强> TL; DR

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

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

我如何进行身份验证,类似于之前版本的.Net版本,旧方法仍然有用或是否有更新的版本。

我认为没有理由不能在ASP.NET Core中实现旧方法,但总的来说,该策略已被ASP.NET身份所取代,并且ASP.NET身份在ASP中仍然存在。 NET核心。

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

ASP.NET Identity使用像SQL Server这样的后备存储来保存用户信息,如用户名,密码(散列),电子邮件,电话,并且可以轻松扩展以保存FirstName,LastName或其他任何内容。因此,没有理由将用户信息加密到cookie中并在客户端之间来回传递。它支持用户声明,用户令牌,用户角色和外部登录等概念。以下是ASP.NET标识中的实体:

  • AspNetUsers
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins(用于链接外部身份提供商,如Google,AAD)
  • AspNetUserTokens(用于存储用户积累的access_tokens和refresh_tokens等内容)

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

令牌服务器将是一个生成包含授权和/或身份验证信息的简单数据结构的系统。授权通常使用名为 access_token 的令牌。这将是房子的关键,可以说,让你穿过门口进入受保护资源的住所,通常是网络api。对于身份验证,id_token包含用户/个人的唯一标识符。虽然在access_token中放置这样的标识符很常见,但现在有一个专用协议:OpenID-Connect

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

但如果您只想在应用程序中使用用户表,那么这一切都不是必需的。您不需要令牌服务器 - 只需使用ASP.NET标识。 ASP.NET Identity将您的用户映射到服务器上的ClaimsIdentity对象 - 无需自定义IPrincipal类。

当使用基于云的解决方案或单独的令牌服务器时,如何将其与当前应用程序集成,我是否仍然需要在我的应用程序中使用用户表如何将这两者关联起来? < / p>

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

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

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

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

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

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

如上所述,ASP.NET Identity已经这样做了。创建一个&#34;外部供应商&#34;相当容易。表和数据驱动您的外部登录过程。所以当一个新的&#34; SSO&#34;来吧,只需添加一个新行,其中包含提供商的网址,客户端ID和他们提供给您的秘密等属性。 ASP.NET Identity已经在Visual Studio模板中内置了UI,但请参阅Social Login了解更酷的按钮。

<强>摘要

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

我的道歉是,这不是标记,或者它是否过于介绍。请随意互动以获得您正在寻找的靶心。

附录:Cookie身份验证

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

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

Microsoft.AspNetCore.Authentication.Cookies

Configure Startup.cs下的app.UseMvc方法下(app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationScheme = "MyCookieMiddlewareInstance", LoginPath = new PathString("/Controller/Login/"), AutomaticAuthenticate = true, AutomaticChallenge = true }); 之前):

[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();
}

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

{{1}}

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

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

答案 1 :(得分:7)

<强> TL; DR

我真的想要显示如何正确实现IdentityServer4的完整帖子,但我试图使用所有文本,但它超出了StackOverflow接受的限制,所以相反我会提出一些提示和事情我和#39已经学会了。

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

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

Identity Server 4提示

与我见过的许多其他框架相比,身份服务器4的文档记录非常好,但很难从头开始看到整个图片。

我的第一个错误是尝试使用OAuth作为身份验证,是的,有很多方法可以执行此操作,但OAuth用于授权而非身份验证,如果您要验证使用OpenIdConnect(OIDC)

在我的情况下,我想创建一个连接到web api的javascript客户端。 我查看了很多解决方案,但最初我尝试使用webapi来针对Identity Server调用Authenticate,并且只是因为它是针对服务器进行验证而持续存在该令牌。这种流程可能会起作用,但它有很多缺陷。

最后,当我找到Javascript客户端示例时,我得到了正确的流程。您的客户端登录并设置令牌。然后让你的web api使用OIdc Client,它将验证你是否可以访问IdentityServer。

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

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

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

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

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

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:0)

使用Identity实现社交登录并不困难,但是有一些初始设置涉及,有时您在文档中在线找到的步骤并不相同,通常您可以在平台的开发人员部分找到帮助。试图设置社交登录。身份是替代.net框架的旧版本中的旧成员资格功能。我发现令人惊讶的是,边缘用例,例如将已经拥有的jwt令牌传递给web api,并不在网上示例中的任何地方即使在复数,我相信你不需要你自己的令牌权限来做这个,但我没有找到一个关于如何在不处理自托管服务器的get或post中传递数据的例子。

答案 4 :(得分:0)

ASP.NET身份-这是一种用于验证应用程序(无论是承载身份验证还是基本身份验证)的方式的构建,它为我们提供了现成的代码来执行用户注册,登录,更改密码以及所有操作。

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

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

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