网上关于登录态的文章数不胜数,公司内部的知识库里也有很多现成的总结。但读别人的文章终究不如自己真正消化一遍,因此我决定结合日常工作和学习,写一篇属于自己的小结。希望能以简洁的方式,把常见的登录态方案梳理一遍,既当复盘,也能方便日后查阅。
拖更太久了,现在的技术文章我都不知道还有没有写的意义了。因为这种总结类的,不产生只搬运知识的文章愈发廉价了,我想不出有什么不用 AI 生成的理由了,空闲时间也愈发得少了,好悲哀……
注意
本文包含 AI 生成内容,已进行人工校对。如有缺漏和错误之处,也欢迎指出!
在互联网应用中,登录态的存在,是为了让系统能够“记住用户是谁”。HTTP 本身是无状态的协议,每一次请求都是独立的,如果没有额外机制,服务器无法区分用户的身份,也就无法提供个性化和安全保障。
引入登录态,主要解决以下几个问题:
身份识别:系统需要确认请求的发起者是谁。例如,A 用户和 B 用户访问同一个购物网站时,服务器必须区分他们的身份,才能返回各自的订单、购物车或账户信息。
权限控制:在多角色系统中,不同用户的权限范围往往不同。比如管理员可以管理用户,而普通用户只能操作自己的数据。登录态让系统能够基于用户身份执行正确的权限校验。
个性化体验:有了登录态,系统可以根据用户的历史行为或偏好,提供定制化的内容与功能,比如推荐商品、记住浏览记录等。
安全性与可追踪性:登录态能够限制未认证用户访问受保护的资源,同时在必要时提供审计和追踪手段,例如记录用户操作日志。
登录态的本质是:在无状态的网络协议之上建立用户与会话的映射关系,从而让应用能识别身份、分配权限,并提供连续一致的使用体验。
以下内容参考自:一文搞懂前后端常见登录态方案。
HTTP 基本认证是 HTTP 协议本身提供了一种服务端对客户端进行用户身份验证的方法。 流程如下:

WWW-Authenticate: Basic realm="qq.com",弹出用户名和密码输入框要求用户进行验证。这是一种比较简单的验证用户身份的方式,甚至不需要写代码,只要后端服务器配置一下即可。
Cookie 是客户端请求服务端时,由服务端创建并由客户端存储和管理的小文本文件。Session 则是客户端请求服务端时服务端会为这次请求创建一个数据结构,这个结构可以通过内存、文件、数据库等方式保存。一般来说两者搭配使用,服务端可以根据 Cookie 中的 SessionID 获取到相应的 Session。

Token 又叫令牌,是服务端生成用来验证客户端身份的凭证,客户端每次请求都携带 Token。 Token 一般由以下数据组成:

| 认证方式 | 优点 | 缺点 |
|---|---|---|
| Basic Auth(基础认证) | 兼容性好,主流浏览器都支持 | 不安全,账号密码仅 Base64 编码,容易被解码;无法主动注销,除非关闭标签页或浏览器 |
| Cookie & Session | Cookie 由客户端管理,支持设定有效期、安全加密、防篡改、请求路径等属性;Session 由服务端管理,支持有效期,可以存储各种数据 | Cookie 只能存储字符串,大小和数量有限制,对移动端支持不好,存在跨域限制;Session 占用服务端资源,客户端量大时影响性能;集中存储(如 Redis)增加部署维护成本 |
| Token(如 JWT) | 客户端可存储在 Cookie、LocalStorage 等,服务端无需存储;安全性高(签名校验);支持移动端;支持跨域 | Token 比较大,占用传输带宽;每次签名校验增加服务端开销;有效期通常较短,需要刷新机制 |
为了避免被盗用 Token 一般有效期比较短。但是有效期太短会造成客户端不断重新登录,体验太差。因此我们可以再来一个 Token,一个专门生成 Token 的 Token,称为 Refresh Token。

注意
后续文本包含 AI 生成内容,已进行人工校对
此外,服务端校验客户端发过来的 Token 时,可能需要查询数据库,以确认 Token 是否有效、用户是否仍然可用等。如果每次请求都访问数据库,会带来额外的性能开销。
一种优化方式是使用 JWT(JSON Web Token)。JWT 是一种 Token 格式,可以将用户 ID、过期时间等声明放在 Token 中,并通过数字签名保证这些内容未被篡改。JWT 通常由三部分组成:Header(头部)、Payload(负载)和 Signature(签名),中间用点(.)分隔。
这样,服务端可以通过验证签名、检查过期时间等方式,在不查询数据库的情况下完成基本校验,从而减少数据库访问。
但这并不意味着使用 JWT 后就一定不需要查询数据库:如果业务需要检查用户是否被禁用、权限是否已变更,或者 Token 是否已被主动撤销,仍然可能需要额外的查询或其他机制。
SSO(Single Sign-On,单点登录)是一种身份认证机制,核心目标是:用户只需要登录一次,就可以访问多个相互信任的应用,而不需要在每个应用中重复登录。
例如,公司内部有 OA、代码托管平台、项目管理系统等多个应用。如果没有 SSO,用户可能需要分别登录这些系统;接入 SSO 后,用户登录统一认证中心,就可以在访问其他应用时复用已有的登录状态。
这里需要注意,SSO 并不是一种独立的 Token 格式,而是一套跨应用共享认证结果的机制。它可以结合 Cookie、Session、Token 等技术实现。
假设有三个角色:
典型流程如下:
因此,SSO 并不意味着多个应用直接共享同一个 Session 或 Cookie。更常见的做法是:认证中心维护统一的登录状态,各业务应用分别建立自己的本地会话,通过可信的认证流程建立关联。
一种常见的实现方式是基于共享域 Cookie。例如,多个业务系统部署在同一个主域名下,可以在满足浏览器 Cookie 规则和安全要求的前提下,共享特定域的 Cookie。但这种方式耦合较强,不适用于所有跨域场景。
另一种更通用的方式是通过认证中心完成重定向认证。业务应用不需要直接读取认证中心的 Cookie,而是通过跳转、回调以及凭证验证来确认用户身份。这种方式更适合多个独立应用,也可以基于 OAuth 2.0 / OpenID Connect 等标准协议实现。
SSO 解决的是多个应用之间的登录体验和认证协同问题,而 OAuth 2.0 主要解决授权问题。两者可以配合使用,但概念并不相同。
OAuth 2.0 是一种授权框架,用于让第三方应用在获得用户授权后,访问用户在某个服务中的受保护资源,而不需要直接获取用户的账号密码。
例如,一个图片管理应用希望读取用户网盘中的照片。传统做法可能是让用户直接向第三方应用提供网盘账号密码,这不仅风险高,也无法精细控制第三方应用能够执行的操作。
OAuth 2.0 则允许用户在网盘的授权页面确认授权范围,由网盘向第三方应用签发访问令牌。第三方应用凭借该令牌访问允许访问的资源,而不需要知道用户的网盘密码。
OAuth 2.0 定义了几个核心角色:
授权服务器与资源服务器可以由同一套系统提供,也可以是相互独立的服务。
目前,Web 应用中常见的授权流程是 Authorization Code Grant(授权码模式)。下面以第三方应用访问网盘资源为例说明。
scope、随机参数 state 等信息。code。code_verifier。这里的关键是:浏览器回调传递的是授权码,而不是直接把用户密码交给第三方应用。 授权码通常具有短有效期,并且只能使用一次;Access Token 则用于访问受保护资源。
在实际开发中,应使用精确匹配的回调地址,并通过 state 等机制防范请求伪造。对于授权码流程,尤其是无法安全保存客户端密钥的公开客户端,应使用 PKCE(Proof Key for Code Exchange)来降低授权码被截获或注入后遭到滥用的风险。现代 OAuth 安全实践也推荐在授权码流程中使用 PKCE。
Access Token 是客户端访问受保护资源的凭证。它可以是不透明的随机字符串,也可以采用 JWT 等格式,具体取决于授权服务器的设计。
scope 用于表达客户端申请或获得的授权范围。例如:
profile:read:读取用户资料。photo:read:读取照片。photo:write:修改照片。这些名称只是示例,实际权限名称由具体系统定义。资源服务器必须根据实际签发的权限执行校验,不能仅因为客户端携带了一个有效令牌,就允许它访问所有资源。
需要特别区分的是:OAuth 2.0 主要解决授权,不直接定义统一的用户身份认证协议。
假设某个第三方应用获得了网盘的 photo:read 权限,这只能说明它获得了访问照片的授权,并不能单凭这个事实,就断定当前登录该第三方应用的用户是谁。
如果需要基于第三方身份提供“使用某账号登录”的能力,通常会使用 OpenID Connect(OIDC)。OIDC 在 OAuth 2.0 之上增加了身份认证层,并通过 ID Token 等机制向客户端提供经过验证的用户身份信息。
因此,可以简单记为:
这也是为什么接入第三方登录时,不能只看到 OAuth 2.0 和 Access Token 就认为整个身份认证流程已经完成。
第三方登录是指应用允许用户使用其他平台已有的账号完成登录,例如使用微信、QQ、GitHub 或 Google 账号登录,而不必为当前应用重新注册一套账号密码。
从实现角度看,第三方登录通常会借助 OAuth 2.0 或 OpenID Connect 等协议,但不同平台提供的接口、授权流程和用户信息获取方式可能有所差异。
以用户使用第三方平台账号登录某个网站为例:
需要注意,第三方平台的身份与本地业务账号并不是同一个概念。第三方平台负责证明用户在该平台上的身份,而当前应用仍然需要管理自己的用户、权限和会话。
通常不建议直接使用昵称、头像或邮箱作为唯一关联依据,因为这些信息可能重复、变更,或者无法被可靠验证。
更稳妥的做法是保存第三方平台标识和该平台提供的稳定用户 ID,例如:
(provider, provider_user_id) -> local_user_id
其中,provider 表示第三方平台,provider_user_id 表示用户在该平台内的唯一标识,local_user_id 则是当前应用自己的用户 ID。
对于支持多个应用或多个开发者账号的平台,还需要考虑用户标识的作用域。例如,某些平台的用户 ID 只在特定应用或开发者范围内唯一,不能脱离对应的应用标识直接使用。
state,并在适用时使用 PKCE。第三方登录主要解决的是身份来源问题:用户可以借助已有账号证明自己的身份,但当前应用仍然需要决定如何将这个身份映射到自己的用户体系中。
扫码登录是指用户通过手机等已登录设备扫描网页上的二维码,从而完成另一个设备或客户端的登录。它常见于网页版即时通信软件、电视应用、开发者工具等场景。
扫码登录并不是一种独立的认证协议,而是一种交互方式。二维码背后可以采用一次性票据、设备配对、临时授权码等机制来实现身份确认。
以电脑浏览器登录某个应用为例:
实际系统可能会将流程拆分成“待扫码”“已扫码待确认”“已确认”“已过期”等状态。扫码与确认是两个不同的步骤:仅仅扫描二维码,并不一定意味着用户已经同意登录。
二维码中通常不应该直接包含用户的长期登录 Token、账号密码或其他可长期使用的敏感凭证。
更合理的设计是放入一个随机、不可预测、具有短有效期的临时标识。服务端将它与本次登录会话关联,并在收到手机端的授权确认后更新状态。
这样,即使有人截取了二维码,也不应当仅凭二维码内容就能够直接获得长期登录权限。
此外,还应注意以下问题:
扫码登录的本质,是利用已经完成身份认证的设备,为另一个设备发起的登录请求进行授权。它改变的是用户确认身份的交互方式,而不是取消服务端对身份和权限的验证。
手机号一键登录是一种利用运营商提供的号码认证能力,简化用户登录或注册流程的方式。用户通常只需要点击确认按钮,就可以在满足运营商和客户端环境要求的情况下,完成手机号验证,而不必手动输入短信验证码。
传统短信验证码登录与手机号一键登录的区别在于:前者通常要求用户接收并输入短信中的验证码;后者则由运营商或号码认证服务商提供相应的验证能力,应用通过服务端接口验证结果。

具体实现取决于运营商和服务商提供的 SDK 与接口。有些方案会先通过客户端 SDK 获取临时 token,再由后端向服务商换取认证结果;有些方案的流程则有所不同。
| 对比项 | 短信验证码登录 | 手机号一键登录 |
|---|---|---|
| 用户操作 | 接收并输入验证码 | 通常点击确认即可 |
| 验证方式 | 校验短信验证码 | 调用运营商或号码认证服务验证 |
| 用户体验 | 操作步骤较多 | 操作更便捷 |
| 依赖条件 | 能接收短信即可 | 取决于运营商、SDK、设备及网络环境 |
| 成本与接入 | 需要短信发送与验证服务 | 通常需要接入号码认证服务,可能产生相应费用 |
手机号一键登录主要改善的是用户输入和身份验证的体验。它并不会替代应用自身的用户体系,也不意味着手机号可以永久代表某个自然人。
回过头来看,这些登录态方案其实解决的是不同层面的问题。
它们并不处于同一个层级,因此实际系统经常会组合使用多种机制。例如,用户通过 OIDC 完成第三方登录,应用再通过 Cookie + Session 维护自己的登录态;或者使用 OAuth 2.0 授权码流程获取访问令牌,再通过 Refresh Token 续期。
真正设计登录态时,除了考虑流程是否能够跑通,还需要关注凭证的存储、传输、过期、撤销、权限范围以及被盗用后的影响。登录成功只是身份认证的开始,如何安全地维持和管理登录状态,才是登录态设计的核心。
登录态
JWT
SSO
OAuth2
扫码登录
手机号一键登录
本文作者:Zerol Acqua
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!