## 整体架构图 下面是解决方案整体架构图: ![](https://img.kancloud.cn/a1/7c/a17c242d32b028e6f391f69d4e401711_580x395.png) 如图所示,有六个应用程序和一个数据库,下面提供了更多的信息: * **身份验证服务器**:此服务用于登录、注册和管理用户帐户。它基于 ABP 的标准**Account**模块,该模块基于该`IdentityServer`库。它是**单点登录**(**SSO**) 服务,这意味着如果您登录/退出到其中一个应用程序,那么您将登录/退出到所有应用程序。那是一个ASP.NET Core Razor Pages 应用程序,它直接连接到数据库。 * **主站**:这是最终用户用来注册和创建活动的平台 ([www.openeventhub.com)](http://www.openeventhub.com/)它是一个使用**Main HTTP API**作为后端的Razor Pages应用程序。 * **管理员后台**:此应用允许管理员管理组织、事件和系统。它使用**Admin HTTP API**进行所有操作,这是一个**Blazor WebAssembly**应用。 * **主站 HTTP API**:主网使用调用的 HTTP API接口。 * **Admin HTTP API**:管理员后台调用的 HTTP API。 * **后台服务**:运行系统后台进程服务和后台作业的**控制台程序。** * **数据库**:这是一个关系型 **PostgreSQL**数据库,用于存储系统中的所有数据。 由于是分布式系统,所以使用**Redis**作为分布式缓存服务器。 我们先从身份验证流程开始。 ## 认证流程 如前所述,**Authentication Server**是一个 SSO 服务,用于对用户和客户端进行身份验证。当用户想要登录时,**主网站**和**管理员后台**使用**OpenID Connect**(**OIDC**) 协议将用户重定向到\*\*身份验证服务器。\*\*下图显示了登录过程: ![](https://img.kancloud.cn/f2/ed/f2ed851331a932337b11b995edd090bf_506x560.png) 它的逻辑顺序是这样的: * 当用户想要访问主站时 **(1)**,主站将用户重定向到身份验证服务 **(2)**。 * 身份验证服务有一个登录页面,用户可以输入用户名和密码或注册为新用户。登录完成后,用户将重定向回主站,并返回授权码 **(3)** 和 **(4)**。 * 然后,主站使用获得的授权码向服务器执行令牌请求 **(5)**。 * 身份验证服务返回一个标识符(包含一些用户信息,例如用户名、ID、电子邮件等)和一个访问令牌 **(6)**。 * 主站将访问令牌存储在 cookie 中(管理员后台将令牌存储在浏览器的本地存储中),以便在下一个请求中获取。在接下来的请求中,它从 cookie 中获取访问令牌并将其添加到 HTTP 请求头中,同时对Main HTTP API执行 HTTP 请求 **(7)**。 * Main HTTP API 验证访问令牌 **(8)** 并授权请求。 所有这些过程都由 ABP的`Account`和`IdentityServer`模块完成。 ## 探索解决方案 [EventHub.NET](http://EventHub.NET) 解决方案由多个项目组成,按应用类型分组,如下图所示: ![](https://img.kancloud.cn/0a/5f/0a5fcaea1df884c36359975db63e96ec_302x470.png) 该解决方案有两个应用层和一个领域层,以及相应的 HTTP API 和**用户界面**(**UI**) 层。两个应用层共享领域层,但它们具有不同的应用程序逻辑,因此它们是分开的。 ### common 文件夹 我们先介绍`common`文件夹。该文件夹包含通用库和服务,如下所述: * `EventHub.Domain`项目是包含实体、领域服务和其他领域对象的领域层。`EventHub.Domain.Shared`项目包含常量和一些其他类,它们是所有层和应用的共享层。 * `EventHub.EntityFrameworkCore`项目包含`DbContext`、映射、数据库迁移、存储库实现以及与 EF Core 相关的其他代码。 * `EventHub.DbMigrator`项目是一个控制台应用,用于数据库迁移并初始化数据(例如管理员用户/角色及其权限),支持开发和生产环境。 * `EventHub.BackgroundServices`项目是另一个控制台应用,用于运行后台作业。 ### www 文件夹 `www`文件夹包含主站项目: * `EventHub.Application`包括应用服务的实现,`EventHub.Application.Contracts`包括应用服务接口和DTO。 * `EventHub.HttpApi`包含 UI(Web)层使用的 API 控制器,该控制器是应用服务的简单包装器。 * `EventHub.HttpApi.Host`托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离(重用`EventHub.HttpApi`)。 * `EventHub.HttpApi.Client`一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。 * `EventHub.Web`是应用程序的 UI 层。这是一个典型的 Razor Pages 应用。它没有数据库连接,调用**Main HTTP API**进行操作。 * `EventHub.Web.Theme`自定义主题。ABP 有一个主题系统,您可以使用它来构建自己的主题并在其他应用中重用它们。`EventHub.Web`项目使用此主题。主题系统将在*第 4 部分*,*用户界面和 API 开发*中介绍。 ### admin 文件夹 `admin`文件夹包含管理员后台,由维护系统的用户使用,这里有更详细的解释: * `EventHub.Admin.Application`项目是管理员后台的应用层,包含应用服务的实现,`EventHub.Admin.Application.Contracts`包含与UI层共享的应用服务接口和DTO。 * `EventHub.Admin.HttpApi`包含 UI(Web)层使用的 API 控制器。 * `EventHub.Admin.HttpApi.Host`项目托管 HTTP API 层。通过这种方式,托管逻辑与包含 API 控制器的项目分离。 * `EventHub.Admin.HttpApi.Client`项目是一个调用 API 的客户端。UI (web) 层使用该项目来调用 HTTP API。该项目使用 ABP 的动态 C# 代理功能。 * `EventHub.Admin.Web`项目是应用程序的 UI 层。这是一个在浏览器中运行并对服务器执行 HTTP API 调用的Blazor WebAssembly应用。 ### account 文件夹 `account`文件夹包含单个项目`EventHub.IdentityServer`,其他应用程序使用该项目对用户进行身份验证。 我们已经简要地介绍了解决方案中的所有项目,下面介绍项目之间的依赖关系。 ## 项目依赖关系 在接下来的部分中,我将展示每个项目的依赖关系图,以便您了解代码库的组织方式。我们从基本应用程序**主站开始。** ### Main Application(主站) 请记住,**主站**是互联网**终端用户**使用应用程序:[www.openeventhub.com](http://www.openeventhub.com/)。下图显示了项目依赖关系,从应用程序的根项目`Web`开始: ![](images/screenshot_1650540632152.png) 该`Web`项目依赖于`Web.Theme`,它实现了 EventHub 的 UI 主题。`Web.Theme`是一个单独的项目,因为它同时被**Authentication Server**复用。 项目`Web`也依赖于`HttpApi`项目。我们可以在Web项目的客户端 (JavaScript) 中调用这些 API,当您通过`HttpApi.Client`调用 HTTP API 时,请求将重定向到 **Main HTTP API** (后端)。 >[success] 请注意,`HttpApi`和`HttpApi.Client` 都引用了`Application.Contacts`项目。 `HttpApi`引用`.Contracts`接口层,而`HttpApi.Client`使用 ABP 的动态 C# 代理实现了这些接口,并通过执行HTTP远程调用**Main HTTP API**。 ### Main HTTP API(主站API) **主站**使用**Main HTTP API**作为后端 API。它包含应用领域逻辑。下图显示了根项目`HttpApi.Host`及其直接或间接依赖项: ![](https://img.kancloud.cn/fe/1e/fe1eec341c709c8724137f5246f7a719_589x256.png) * 通过引用(添加依赖)`HttpApi`项目(包括 API 控制器),客户端可以响应 HTTP API 调用; * HTTP API 控制器使用`Application.Contracts`项目中定义的服务接口,而这些接口由`Application`项目实现,这就是为什么我们需要在`HttpApi.Host`项目中引用`Application`项目,而`Application`往下依赖的是`Domain`层,通过它来执行业务逻辑。 * `HttpApi.Host`项目还引用了该`EntityFrameworkCore`项目,因为我们在运行时需要一个数据层。该`EntityFrameworkCore`项目将实体映射到数据库中的表,并实现了`Domain`项目中定义的存储库接口。 请注意,`Application.Contracts`项目,以及`Domain.Shared`项目由客户端程序**Main Website**共享(以及`Domain.Shared`项目是间接被共享),因此它们可以依赖相同的应用程序接口进行通信。 我们现在已经了解了**主站**应用程序,下一部分介绍管理员后台: ### Admin Application(管理员站) 管理员后台站点的前端采用的是Blazor WebAssembly技术,它有一组不同的 API、UI 页面、授权规则、缓存要求等。它有不同的应用层和 HTTP API 层,共享相同的领域层,使用相同的领域逻辑和相同的数据库。 如下图所示: ![](https://img.kancloud.cn/40/f1/40f1d8087660111764283c8570e70477_404x259.png) 此图很简单。`Admin.Web`项目(即 Blazor WebAssembly )引用`Admin.HttpApi.Client`项目,因为它需要调用远程 HTTP API。而项目`Admin.HttpApi.Client`依赖于`Admin.Application.Contracts`项目(内部依赖于`Domain.Shared`项目),目的是要使用其中定义的应用服务接口。 ### Admin HTTP API(管理员站 API) 管理员站点调用**Admin HTTP API**。它运行着管理员后台的应用逻辑。下图显示了根项目`Admin.HttpApi.Host`及其直接和间接依赖项: ![](https://img.kancloud.cn/21/c9/21c9ca6813e2647f3322db488a2cde0c_595x256.png) 该图与**Main HTTP API**非常相似。区别在于他们具有不同的 HTTP API 和应用层。但是使用相同的**领域**和数据库集成 (`EntityFrameworkCore`) 层。 ### 认证服务器 **Authentication Server**的根项目是`IdentityServer`,依赖关系如下: ![](https://img.kancloud.cn/0b/a7/0ba779c6d95996000032b4f40a9375da_416x259.png) `IdentityServer`项目和主站一样,也引用`Web.Theme`,它还引用了`EntityFrameworkCore`项目。通过引用`EntityFrameworkCore`项目,也间接引用了`Domain`和`Domain.Shared`项目。 ### 后台服务 `BackgroundServices`项目具有下图所示的依赖项: ![](https://img.kancloud.cn/99/0a/990a77f0a8807539ea564629d240b407_389x235.png) `BackgroundServices`项目引用`EntityFrameworkCore`,以便操作数据库,它还可以使用**领域**对象(实体、域服务)来执行后台任务。 我们已经介绍完了解决方案中的所有项目。现在,我们准备在本地开发环境中运行它们。