添加feature

生产中的真实系统需要的不仅仅是生成的 CRUD 端点。他们需要安全性、权限、异步处理、操作作业、事件发布,以及在 SaaS 场景中的每tenant隔离。


Lino 将这些feature添加为标准feature。每个feature都会更新项目元数据、生成源代码、添加配置并使后端、前端、消息传递和持久性与同一架构保持一致。

认证与授权

身份验证feature添加了 Lino 项目使用的安全基础,以保护 API、识别用户、控制对操作的访问并将相同的权限与 Blazor Web 应用程序集成。 它是使用以下命令安装的:

lino feature auth add --service <ServiceName> --module <ModuleName>

该命令也可以交互执行 lino feature auth add。 规范分支是 feature auth; CLI 还公开了别名,例如 feature securityfeature identity

在当前的Lino架构中,身份验证和授权依赖于异步消息传递。 原因是可操作的:服务和模块权限通过集成事件同步,因此项目需要在添加安全性之前启用消息传递。

向导要求什么

CLI 验证当前项目,检查该feature是否尚未安装,询问应在何处创建安全模块并请求主要令牌设置。

  • 服务:将托管安全资源的服务。
  • 模块:当所选服务是模块化时的目标模块。
  • 访问令牌的生命周期:颁发的访问令牌的生命周期(以分钟为单位)。
  • 刷新令牌生命周期:用于更新会话的令牌的生命周期。
  • 用户标识符类型:用作用户标识符的数据类型,例如 int, long 或者 Guid

生成的安全模型

确认后,Lino 更新项目元数据、创建安全配置值、生成源代码文件并运行必要的命令。 生成的模型包括中央安全实体:

  • User 存储身份和个人资料数据。
  • Role 以及与组访问规则的角色关联。
  • Permission 以及角色和权限之间的关系以进行精细授权。
  • UserToken 用于控制刷新令牌和令牌生命周期。

该feature还会创建安全配置所需的信息,例如令牌签名密钥以及 access token 和 refresh token 的生命周期。 敏感值作为命令发送给 AppHost 用户secrets,而不是直接写入版本文件。

运行时行为

API 使用 JWT Bearer 身份验证。用户登录后接收 access token 和 refresh token,并使用 Authorization: Bearer <token> header 向 API 发送请求。 后端验证令牌、加载用户上下文并将授权规则应用于端点。

典型的流程仍然很简单:通过端点或专用页面登录,发出具有身份声明、角色和权限的 JWT,在每个请求中发送令牌并通过身份验证中间件验证签名和过期。

Lino通过策略和权限实现细化授权。每个操作可能需要特定的许可,例如 People.Read 或者 People.Create;策略可以通过配置 AddAuthorization;并且可以通过声明来保护端点 .RequireAuthorization

生成的端点和页面一致地使用权限。后端操作可能需要权限,而生成的 Blazor UI 可以在项目中有 Web App 时加载权限、保护页面、隐藏不可用的操作以及暴露用户、角色、权限和授权的屏幕。

当Background Job已启用时,Lino 还会添加与用户令牌相关的作业,例如禁用或过期令牌的维护例程。

后台处理和 Outbox

后台处理处理不应阻塞主请求和响应流的工作:发布集成事件、清理旧记录、删除过期令牌、发送通知、生成报告、与外部系统同步或运行计划任务。 Lino 通过Background Jobfeature添加此feature:

lino feature background-job add --service <ServiceName>

该命令也可以执行为 lino feature background-job add 并以交互方式完成。 CLI 将别名公开为 job-schedulerworker

此feature需要在项目中启用消息传递,因为它的主要职责是安全地发布由 Transactional Outbox 标准注册的消息。

向导要求什么

  • 服务:将安装Background Job基础设施的服务。
  • Background Job库:用于执行和调度作业的实现。当前生成的基础设施使用Hangfire。
  • Outbox 处理:定义服务是否将注册要由调度程序处理的事件。
  • CronOutbox消息:用于检查新消息 Outbox 的范围或计划表达式。
  • 批量大小:每个周期检索和处理的 Outbox 记录数,控制负载、并行性和资源消耗。

Hangfire 基础设施

Lino 生成必要的基础设施来注册 Hangfire、配置其持久性、公开仪表板并安排服务使用的作业。 生成的配置包括调度 jobs、处理 Outbox 消息以及保护调度程序仪表板访问所需的信息。

在生成的解决方案中,Hangfire 架构和表是应用程序数据库配置的一部分。 仪表板可帮助您检查开发和操作期间已完成、失败、计划和重复的作业。

实际好处包括异步任务的可靠执行、内置监控仪表板、对重复或计划作业的支持以及数据库中作业的持久性。

使用事务性 Outbox 进行处理

为了确保异步集成的一致性,Lino 使用事务性 Outbox 模式。 业务用例保留域更改并在同一事务中的 Outbox 表中记录集成事件。 然后,Background Job读取 Outbox 表并通过配置的消息总线发布事件,例如为项目选择这些选项时使用 MassTransit 的 RabbitMQ。

  1. 命令更改域的状态并将此更改保存在事务中。
  2. 处理程序在 Outbox 中注册集成事件,例如与订单创建相关的事件。
  3. Hangfire 作业会阻止一批未处理的消息,并将这些消息标记为正在处理。
  4. 每条消息都由事件总线反序列化并发布。
  5. 成功的消息被标记为已处理;失败的消息会保留错误信息以供以后分析或重试策略。

其结果是数据库和记录的事件之间的原子性、可靠性(以便在发生故障时事件不会丢失)以及可扩展性(以便多个使用者处理已发布的消息)。

生成的作业还包括用于删除已成功处理的旧 Outbox 消息并释放陷入处理过程的消息的例程,从而降低应用程序故障后永久锁定的风险。

安装身份验证后,Background Jobfeature还可以托管令牌维护作业,从而随着时间的推移保持安全数据的干净。

凭借这些附加feature,Lino 可以提供强大的安全性、精细的访问控制和可靠的异步处理,以满足现代生产应用的关键要求。

多tenant

多tenant是当同一应用程序需要为多个客户端、组织或环境提供服务,同时维护每个tenant的独立数据、权限和配置时使用的feature。 在Lino中,添加了tenant支持:

lino feature tenant add --service <ServiceName> --module <ModuleName>

该命令也可以交互执行 lino feature tenant add。 CLI 分支还公开了别名,例如 tenancy

先决条件

tenant支持取决于两个架构feature:

  • 认证与授权,因为用户访问、角色、权限和令牌需要是tenant感知的。
  • 消息传递,因为tenant和用户信息可以通过集成事件传播到其他模块。

如果缺少这些先决条件,该命令将被拒绝。每个项目也只能安装该feature一次。

生成了什么

Lino 创建一致管理tenant所需的租赁模型、配置、事件、API 集成和前端资源。

  • Tenant 存储 tenant 身份、名称、slug、状态、隔离模式和连接字符串引用。
  • TenantBranding 存储每个tenant特定视觉行为的品牌数据。
  • TenantDomain 将主机或域映射到tenant。
  • TenantStatusIsolationMode 定义tenant生命周期和数据隔离选项。
  • 生成的配置支持项目的 tenant 解析和数据隔离。

tenant感知的安全

租赁改变了身份验证和授权的解释方式。在当前tenant的上下文中评估有效的令牌和权限;在一个tenant中拥有访问权限的用户不会自动获得对另一tenant的访问权限。 因此,tenant支持更新身份验证流程、刷新令牌行为、为 UI 生成的权限和引用。

在生成的 Blazor 应用程序中,可以添加tenant感知屏幕来管理tenant和授权流程。 在后端,生成的端点可以从配置的主机、slug 或路由行为解析tenant上下文,然后在数据和授权决策中应用tenant标识符。

数据隔离和传播

Lino 通过允许实体在每个tenant的基础上声明所有权来支持tenant感知域建模。 在 SaaS 场景中,这允许业务表存储特定于tenant的数据,同时共享模块继续接收所需的tenant和用户信息。

生成的体系结构使用事件和 Outbox 模式在模块之间传播选定的tenant或用户数据,而无需将所有模块直接耦合到原始身份或tenant表。 这使模块边界保持清晰,同时屏幕、API、权限和查询继续与tenant上下文一起操作。

添加tenant后,为受影响的服务创建并应用迁移,检查生成的secrets和 API 密钥,运行 AppHost 并使用至少两个tenant进行验证,以确保数据、用户、角色、权限和业务记录保持隔离。

  • 验证隔离: 创建尝试访问另一个tenant的数据的测试。
  • 审核权限: 一个用户可以在不同的tenant中拥有不同的角色。
  • 避免信任客户: 通过路由、主机、slug 或标头通知的tenant必须与经过身份验证的用户兼容。
发生了未处理的错误。 重新加载 🗙