内容翻译自github:Stateful-vs-Stateless-Authentication;
身份验证是几乎每个应用程序中存在的一个过程,用于确定应用程序的客户端是用户还是其他应用程序。在身份验证过程中,客户端向应用程序发送凭据。应用程序确保凭据正确无误,生成身份验证令牌并将其发送回客户端。为了以已识别的客户端身份访问应用程序,客户端使用收到的身份验证令牌。
身份验证令牌可以是有状态的和无状态的。
有状态身份验证
在成功身份验证后,应用程序生成一个随机令牌发送回客户端,然后在内存或内部数据库中创建一个经过身份验证的客户端会话。当客户端尝试使用给定的令牌访问应用程序时,应用程序尝试从会话存储中检索会话数据,检查会话是否有效,然后决定客户端是否有权访问所需资源。
无状态身份验证
在成功身份验证后,应用程序生成一个包含所有必要数据的令牌,使用公钥对其进行签名,并将其发送回客户端。有一个关于令牌生成的标准,即JWT(JSON Web Token)。该过程在OpenID Connect(OIDC)规范中有描述。当客户端尝试使用令牌访问应用程序时,应用程序使用私钥验证令牌签名,检查令牌是否过期,从令牌中检索所有会话数据,并决定客户端是否有权访问所需资源。
有状态 (Stateful) | 无状态 (Stateless) | |
---|---|---|
会话信息可能被窃取 | ✅ 无法从会话标识符中窃取会话信息,因为它只是与会话关联的标识符。 | ⛔ 会话标识符包含所有认证信息,可能会窃取敏感信息,未加密。 |
资源消耗 | ⛔ 当检索会话信息时,服务始终访问会话存储,这会导致额外的资源消耗。 | ✅ 会话标识符包含所有会话信息。 |
实现简易性 | ⛔ 当会话信息存储在外部数据库中时,需要实现会话数据库持久性。 | ✅ 会话标识符包含所有会话信息,无需实现额外功能。 |
扩展简易性 | ⛔ 添加新实例时,需要实现会话存储的额外扩展性。 | ✅ 添加新的服务实例不需要额外的工作。 |
可能危及会话数据 | ✅ 只有认证系统能够从认证令牌中检索会话信息,因此没有更多的漏洞。 | ⛔ 要解密令牌中的会话信息,系统的所有部分都应共享相同的密钥。而且,如果至少有一个系统受到威胁,整个系统的所有部分都会受到威胁。 |
认证令牌大小 | ✅ 认证令牌只是一个标识符,因此会话数据不会影响其大小。 | ⛔ 如果认证会话包含大量数据,则认证令牌也会变大,可能会对网络造成额外负载。 |
限制应用程序不同部分的访问 | ✅ 可以配置系统,使系统的不同部分只能访问其工作所需的数据。 | ⛔ 系统的所有部分都可以访问所有会话数据。 |
撤销会话的可能性 | ✅ 可以随时撤销会话。 | ⛔ 由于会话令牌包含过期日期,因此无法撤销认证会话。 |
修改会话数据的可能性 | ✅ 可以修改会话数据存储中的任何会话数据。 | ⛔ 由于会话令牌包含所有会话数据,无法对其进行修改。 |
SSO 实现 | ✅ 可以在不修改源代码的情况下集成系统的不同部分,会话信息可以通过认证系统网关传递。 | ⛔ 必须对系统的每个部分进行更改,以从认证令牌中检索数据。 |