ASP.NET Core:使用 IdentityServer 构建强大的身份验证和授权系统






4.11/5 (7投票s)
使用 IdentityServer 和 ASP.NET Core 3.1 构建强大的身份验证和授权系统
OAuth 2.0 到底是什么?
OAuth 2.0 是一种授权协议,它允许用户授予第三方应用程序访问用户资源的权限,而无需透露用户的身份或凭证。需要注意的是,它是一个授权协议,只能用于授权场景,而不能用于身份验证流程。
为什么使用 OpenID Connect?
OAuth 2.0 在解决授权问题方面非常出色,但我们需要一种解决方案来处理用户身份验证用例。聪明的人们聚集在一起,构建了一个高效的解决方案。OpenID Connect 是一个构建在 OAuth 2.0 框架之上的身份协议。
向 IdentityServer 问好!👋
IdentityServer 是一个用于 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 框架。IdentityServer 是 OpenID Connect 的官方认证实现。
根据 IdentityServer
的官方文档,它具有许多职责和功能
- 保护您的资源
- 使用本地账户存储或通过外部身份提供者对用户进行身份验证
- 提供会话管理和单点登录
- 管理和验证客户端
- 向客户端颁发身份和访问令牌
- 验证令牌
Hello World 程序
在本教程中,我们将构建一个中央身份验证系统,该系统将处理 MVC 和 Angular 应用程序访问受保护资源的身份验证请求。
我们将使用 IdentityServer
设置一个中央身份验证系统。然后,我们将创建一个 MVC 应用程序,其受保护的页面可以在通过身份验证服务器进行身份验证后访问。我们还将创建一个 Angular 应用程序,该应用程序将能够在身份验证后访问受保护的 API。
设置中央身份验证系统所需的步骤 — 从 1000 英尺的视角
- 创建 MVC ASP.NET Core 项目
- 添加
IdentityServer
NuGet 包 - 添加 EF Core NuGet 包以存储客户端和配置
- 在 Startup 中配置
IdentityServer
服务 - 在中间件中添加
IdentityServer
管道 - 在数据库中填充客户端和资源数据
- 创建
AccountController
来处理注册和登录场景
从零开始设置身份验证服务器
- 创建一个空的 MVC .NET Core 项目。
- 添加所需的 NuGet 包。
这些是我们设置
IdentityServer
、AspNetIdentity
以及用于持久化的 EF 所需的一些包。 - 让我们在 startup 文件中配置
IdentityServer
、AspNetIdentity
和 EF。让我们来理解一下我们在这里做了什么。首先,我们通过创建自己的
DbContext
配置了实体框架,然后我们使用相同的DbContext
配置了AspNetIdentity
。最后,我们通过提供自定义的ConfigurationDBContext
和PersistedGrantDbContext
来配置IdentityServer
。所有客户端和资源信息将通过这些上下文进行存储。 - 在中间件管道中,我们只需要添加一行代码来配置
IdentityServer
中间件。自定义
DbContext
类using AuthorizationServer.Models; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;namespace AuthorizationServer.Persistence { public class AuthDbContext : IdentityDbContext<AppUser> { public AuthDbContext(DbContextOptions<AuthDbContext> options) : base(options) { }protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.HasDefaultSchema("Identity"); } } }using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Options; using Microsoft.EntityFrameworkCore;namespace AuthorizationServer.Persistence { public class AuthConfigurationDbContext : ConfigurationDbContext<AuthConfigurationDbContext> { public AuthConfigurationDbContext (DbContextOptions<AuthConfigurationDbContext> options, ConfigurationStoreOptions storeOptions) : base(options, storeOptions) { }protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.HasDefaultSchema("Identity"); } } }using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Options; using Microsoft.EntityFrameworkCore;namespace AuthorizationServer.Persistence { public class AuthPersistedGrantDbContext : PersistedGrantDbContext<AuthPersistedGrantDbContext> { public AuthPersistedGrantDbContext (DbContextOptions<AuthPersistedGrantDbContext> options, OperationalStoreOptions storeOptions) : base(options, storeOptions) { }protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.HasDefaultSchema("Identity"); } } }
没什么特别的,我们只是创建了自定义的
DbContext
,以便我们可以拥有自定义的架构名称。 - 在所有
DbContext
连接好之后,我们可以创建一个 seed 类来填充我们的客户端和资源信息。我们可以将所有信息直接添加到数据库,也可以在应用程序启动时填充数据。我们需要客户端的信息,这些客户端将由
IdentityServer
进行身份验证,在我们的例子中,我们有两个客户端,一个是 MVC 应用,另一个是 Angular 应用。我们需要指定允许这些应用程序访问的资源。Angular 应用将需要访问WeatherAPI
以及OpenId
和Profile
。类似地,MVC 应用将需要访问OpenId
和Profile
。我们需要将WeatherAPI
添加为一个范围。客户端的 URL 是应用程序托管的 URL。 - 现在我们需要一个控制器和一个视图来管理用户的注册和登录。AccountController.cs
好了,我们的 AuthenticationServer
已准备好处理身份验证和授权请求。
构建 MVC 应用
假设我们有一个 MVC 应用,其页面是受保护的,只能在身份验证后访问。
我们需要配置其 startup 文件,使其了解 AuthenticationServer
和 Authentication
机制。
AddOpenIdConnect
方法接受选项,我们在其中指定 AuthenticationServer
的 URL、ClientId
、ClientSecret
和 ResponseType
。ClientId
应与我们在身份验证服务器中配置的相同。
现在创建一个 home/secret 视图,并向其控制器/操作方法添加 [Authorize]
属性。之后,如果用户尝试访问 secret 视图,它将把请求重定向到身份验证服务器,在提供有效的用户名和密码后,用户将能够看到该页面。
设置 Angular 应用
对于 Angular 应用,我们需要一些后端 API,应用程序可以与之通信。然后,我们将在 API 中设置身份验证机制。经过身份验证的 Angular 应用会将 JWT 令牌发送到 API,然后 API 将验证该令牌和来自身份验证服务器的声明。
让我们在 API startup 文件中配置身份验证机制。
如果您仔细观察,我们会设置了身份验证服务器的 URL,并且还指定了我们在令牌中想要的声明/范围的名称。
对于我们的 Angular 应用,我们需要一个可靠的 npm
包来处理连接 Angular 应用和身份验证服务器所需的所有样板代码。
我们将 “angular-auth-oidc-client” 包添加到我们的应用中。
该包非常出色,因为它处理了我们的大部分工作,我们只需要编写一个配置函数,在该函数中指定身份验证服务器的 URL、我们想要的声明/范围以及一些重定向 URL。就这样,我们就绪了。
让我们编写一些代码来登录用户,并在成功登录后,调用 API 获取数据,并将从身份验证服务器获得的令牌发送到标头中。
结束语
通过使用 IdentityServer
,我们可以将身份验证/授权逻辑从我们的主应用程序中移出,使其更加松散耦合。IdentityServer
帮助我们创建一个中央身份验证系统。在微服务世界中,我们会创建一个中央身份验证系统,例如通过 IdentityServer
创建的系统。
我已在此处附上代码片段的屏幕截图,但您可以在 GitHub 上找到完整的源代码。
资源
- https://oauth.ac.cn/2/
- https://auth0.com/docs/protocols/protocol-oauth2
- https://openid.net/connect/
- https://auth0.com/docs/protocols/openid-connect-protocol
😄 编码愉快!!
历史
- 2020 年 10 月 5 日:初始版本