在本文中,我们将讨论一种安全地执行身份验证和授权的系统。首先让我们了解一下身份验证和授权之间的区别。
在本文中,我们将看到:
假设我们正在开会,而您是谈话的主持人。要向合适的人询问某事的更新/状态,您需要识别(即验证)此人。即使要与某人共享一些敏感数据,您也需要正确地验证此人的身份。这就是身份验证的作用所在。
现在假设,在同一个会议上,需要做出几个决定。因此,有权做出这些决定的人应该是接电话的人,我们不能让每个人都做所有的事情。显然,有些人没有足够的能力做出一些决定,有些人肯定会试图把事情搞砸。因此,这就带来了授权,它赋予某些人进行某些活动的权利。
为了验证一个人的身份,我们可以为每个人分配一个唯一的短语,如果该人正确地说出了短语和他们的名字,我们就可以说,好的,我们已经识别了这个人。这是通常的用户名和密码方法。当给出正确的凭证时,系统会认为身份有效并授予访问权限。这称为 1FA 或单因素身份验证(SFA)。
SFA 被认为相当不安全。为什么?因为用户在保护登录信息安全方面表现糟糕。多因素身份验证 (MFA) 是一种更安全的替代方案,要求用户以多种方式证明其身份。其中一些方式包括:
一旦通过身份验证,用户就可以继续在应用程序上自由执行操作。应用程序希望在整个旅程中都能识别用户,而不会忘记他们。理想情况下,要求用户每次转到其他页面或执行某些活动时都提供密码是过分的。因此,我们需要一种方法,在用户输入凭据并通过一次身份验证后,保持用户的身份。这称为会话管理。
保持用户身份验证的两种方法:
这两种方法之间的主要区别在于,基于令牌的身份验证是无状态的,因为令牌不需要存储在服务器端。但是对于基于会话的身份验证,令牌也需要存储在服务器端,这使得它成为有状态的。当系统扩展或用户数量增加时,这会带来复杂性。
对于基于令牌的身份验证,我们主要使用 JWT(JSON Web 令牌)。
一旦用户通过身份验证,我们仍然需要确保他们只被允许访问他们有权访问的资源。未经授权访问敏感数据可能会带来灾难。根据最小特权原则,公司通常会设置访问策略,以便默认情况下您可以访问您绝对需要的内容。然后在此基础上,您拥有其他访问权限。划分访问权限的常用方法有:
ACL 的使用范围比 ABAC 或 RBAC 更广 - 例如,授予个人用户对某个文件的访问权限。ABAC 和 RBAC 通常作为公司范围的政策制定。
首先让我们定义系统的功能需求:
在本文的讨论范围内我们不会考虑一些非功能性需求,包括:
交通预测
首先让我们从流量估算开始。假设平均流量为每月 100,000。我们估计每月有 100k 用户流量。这相当于每秒 0.04 个请求。我们需要在 90% 的时间内 500 毫秒内响应每个请求,即我们需要 500 毫秒的 p90 延迟。
assumed_traffic_per_month = 100000 #requests assumed_traffic_per_day = assumed_traffic_per_month / 30 ~= 3350 (assuming on higher end; 3333.33 to be precise) estimated_time_per_request = 500 #ms; P90 of 500ms traffic_per_second = (assumed_traffic_per_month) / (30*24*60*60) = 0.04
服务级别目标 (SLO) :500ms(可接受的最大延迟,与系统负载无关)根据我们的计算,假设特定请求没有发生繁重的处理,则 1 个实例所需的平均容量大约为 35ms 来处理一个请求。
让我们使用上述指标生成另外两个派生指标。
因此,
SLO = 500ms approx_response_time_for_one_request = 35 #ms capacity = SLO/approx_response_time_for_one_request = 500 / 35 ~= 20 load_on_one_instance = 0.04 instances_available = 1 demand = traffic_per_second / instances_available = 0.04
根据需求和可用容量,让我们计算所需的实例总数。
total_units_required = demand / capacity = 0.04 / 20 = 0.002 ~= 1
因此,我们每月可以轻松处理 10 万个请求,每秒处理 0.04 个请求,只需 1 个实例。其中每个单元每秒可以处理 20 个请求,而不会影响 SLO。
存储估算
理想情况下,我们需要存储每个用户的用户详细信息,以便进行身份验证和授权访问。假设 5kb/用户
monthly_new_users = 500 monthly_additional_storage = 500 * 5kb = 2500kb ~= 2GB
因此,假设我们每个月新增 500 名用户,我们将需要 2GB 以上的存储空间。如果我们想保留身份验证日志,则每个身份验证请求预计需要 2kb 的存储空间。
auth_request_size = 2kb #assumption monthly_storage = monthly_visitors * auth_request_size = 100,000 * 2KB ~= 200MB
因此,假设每月流量为 100k,我们每月将需要额外的 200MB。
现在我们已经完成了容量估算。让我们创建支持功能需求所需的数据库模式。
让我们快速浏览一下表格。我们使用了 6 个表格。
系统端点
端点 | 描述 |
---|---|
/登录 | 验证用户凭证。 |
/登出 | 结束用户会话并撤销身份验证令牌。 |
/登记 | 创建新用户。 |
/更新/:用户ID | 更新用户信息。 |
/删除/:用户ID | 删除用户帐户。 |
/授予/:用户ID/:许可 | 授予用户特定权限。 |
/撤销/:用户ID/:许可 | 撤销用户的权限。 |
/检查/:用户ID/:资源 | 检查用户对特定资源的访问。 |
/创建/:用户ID | 创建一个新的用户会话。 |
/过期/:sessionId | 使用户会话过期。 |
/验证/:sessionId | 验证活动用户会话。 |
满足要求
现在,所有一切就绪,让我们看看如何完成所有要求。
登记
登录
会话管理
找回密码
访问控制
审计追踪
表现
在本文中,我们首先了解了身份验证和授权之间的区别。接下来,我们创建了一个身份验证和授权系统。该系统安全可靠,性能出色,同时符合行业标准并满足所有要求。今后,我可能会更新文章的某些部分,以使其保持相关性,并涵盖构建此类系统的更多信息和见解。