我试图了解在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);
}
我的问题是:
TL; DR
IdentityServer =通过OAuth 2.0 / OpenId-Connect进行令牌加密和验证服务
ASP.NET Identity = ASP.NET中的当前身份管理策略
我如何进行身份验证,类似于以前版本的.Net中的方式,旧的方式仍然有效或是否有更新的版本。
我认为没有理由不能在ASP.NET Core中实现旧方法,但总的来说,该策略已被ASP.NET身份所取代,并且ASP.NET身份在ASP.NET Core中很有用。
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity
ASP.NET Identity使用像SQL Server这样的后备存储来保存用户信息,如用户名,密码(哈希),电子邮件,电话,并且可以轻松扩展以保存FirstName,LastName或其他任何内容。因此,没有理由将用户信息加密到cookie中并在客户端之间来回传递。它支持用户声明,用户令牌,用户角色和外部登录等概念。以下是ASP.NET标识中的实体:
使用自己的令牌服务器与创建自己的自定义原则有什么优缺点?
令牌服务器将是生成包含授权和/或认证信息的简单数据结构的系统。授权通常使用名为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类。
当使用基于云的解决方案或单独的令牌服务器时,如何将其与当前应用程序集成,我是否仍然需要在我的应用程序中使用用户表如何关联这两者?
请参阅这些教程,以便将单独的身份解决方案与应用程序集成: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已经这样做了。创建“外部供应商”表和数据驱动外部登录过程相当容易。所以当一个新的“SSO”出现时,只需添加一个新行,其中包含提供者的URL,客户端ID和他们给你的秘密等属性。 ASP.NET Identity已经在Visual Studio模板中内置了UI,但是请参阅Social Login以获取更酷的按钮。
摘要
如果您只需要具有密码登录功能和用户配置文件的用户表,那么ASP.NET身份就是完美的。无需涉及外部机构。但是,如果有许多应用程序需要访问许多api,那么保护和验证身份和访问令牌的独立权限是有道理的。 IdentityServer非常适合,或者查看openiddict-core或Auth0以获得云解决方案。
我的道歉是,这不符合标记,或者它是否过于介绍。请随意互动,以获得您正在寻找的靶心。
附录:Cookie身份验证
要使用cookie进行裸骨身份验证,请按照下列步骤操作。但是,据我所知,不支持自定义声明主体。要获得相同的效果,请使用ClaimPrincipal
对象的Claims列表。
在Visual Studio 2015中创建一个新的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帖子来说似乎有点多了。
TL; DR
我真的想要展示如何正确实现IdentityServer4的完整帖子,但我尝试适应所有文本,但它超出了StackOverflow接受的限制,所以我会找到一些我学到的技巧和事情。
使用令牌服务器与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的项目设置为启动项目。
实现授权和身份验证时有很多可移动的部分,希望这篇文章可以帮助某些人。完全理解身份验证的最简单方法是分开他们的示例,将所有内容拼凑在一起,并确保您阅读文档
我一直使用内置的ASP.NET身份(以及之前的成员身份)授权/身份验证,我最近实现了Auth0(https://auth0.com)并推荐这个尝试。
使用Identity不难实现社交登录,但是有一些初始设置涉及,有时您在文档中在线找到的步骤并不相同,通常您可以在您尝试设置的平台的开发人员部分找到帮助社交登录。身份是替代.net框架的旧版本中的旧成员资格功能。我发现令人惊讶的是,边缘用例,例如将已经拥有的jwt令牌传递给web api,并不在网上示例中的任何地方即使在复数,我相信你不需要你自己的令牌权限来做这个,但我没有找到一个关于如何在不处理自托管服务器的get或post中传递数据的例子。
ASP.NET标识 - 这是一种对应用程序进行身份验证的构建方式,无论是承载还是基本身份验证,它为我们提供了现成的代码来执行用户注册,登录,更改密码等等。
现在考虑我们有10个不同的应用程序,并且在所有10个应用程序中执行相同的操作是不可行的。那种非常脆弱和非常糟糕的做法。
要解决此问题,我们可以做的是集中我们的身份验证和授权,以便每当任何更改都不会影响我们的所有10个应用程序。
身份服务器为您提供了执行相同操作的功能。我们可以创建一个仅用作身份服务的示例Web应用程序,它将验证您的用户并提供一些JWT访问令牌。