登录成功后问题才刚刚开始认证通过之后真正的问题才出现下一次 HTTP 请求到来的时候服务器怎么知道它仍然来自刚才已经认证的hzh为什么 HTTP 会有这个问题场景是这样的hzh输入账号密码登录商城服务器核验成功后返回“登录成功”。五分钟后hzh请求/orders。问题在于第二次请求在应用层面是一次独立请求。即使底层连接可能被复用服务器也不会自动知道这个请求还属于刚才登录的用户。除非请求带上某种可验证的信息证明它和第一次登录建立的身份有关。所以一个完整的机制通常是客户端提交认证材料例如密码。服务端验证认证材料。服务端签发后续请求要用的凭据。客户端在每个需要身份的请求中携带该凭据。服务端验证凭据并恢复或确认用户身份。服务端再根据身份、资源和操作判断权限。登录时完成的是“你是谁”的认证后续请求一般不需要重新输密码而是通过验证凭据来确认这个请求是否仍然代表刚才认证过的用户。换句话说认证建立了身份后续凭据维持了请求 - 身份之间可信的关联。一个可验证的凭据至少要具备三种能力身份关联能关联到hzh。可验证性攻击者不能随便编造一个值就冒充hzh。时效控制过期或退出登录后应该能够失效。Cookie Session最经典的方案那我们用什么来维持这个身份一个经典方案是Cookie Session。这里先记住一句话Cookie 负责携带Session 负责记录。Cookie 是浏览器携带数据的一种机制Session 则是服务端保存的会话状态。它们配合起来才能完成登录态的维持。一个完整的请求流程1. 登录用户提交账号密码服务端验证通过后创建一条 Session例如session_7f3...。把它和用户身份、过期时间等信息存到服务端。把 Session ID 通过Set-Cookie发给浏览器。2. 之后查看订单浏览器之后访问/orders时会自动带上 Cookie 中的sid。服务端用这个sid查找 Session找到对应用户后才知道请求来自谁。需要注意Cookie 本身不是认证机制。它只是浏览器自动携带数据的方式。Session 也不必放在单台应用内存中。有多台后端服务器时可以把 Session 放到 Redis 等共享存储否则第一次请求落到服务器 A第二次落到服务器 BB 就查不到登录状态。认证成功后应该重新生成 Session ID。否则攻击者如果提前让用户带上一个已知 Session ID就可能在用户登录后利用它冒充用户这叫会话固定攻击。Session ID 必须具有足够高的随机度。服务器不相信 Cookie 里自称的用户而是用这个随机 ID 查找自己保存的记录。所以可以做到删除服务端的 session_7f3... - 浏览器发送旧 Cookie - 服务端查不到有效会话 - 登录失效退出登录时发生什么如果用户退出登录后浏览器意外又发送了旧的sid服务端该怎么处理用户请求POST /logout携带sidsession_7f3...。服务端删除或标记session_7f3...失效。服务端通过Set-Cookie指示浏览器删除 Cookie这是辅助动作。旧sid再出现时服务端查不到有效 Session返回401 Unauthorized。真正让旧凭据失效的关键是第 2 步服务端不再认可这条 Session。浏览器是否成功删掉 Cookie不能作为唯一依赖。Token、Session 和 JWT 到底是什么关系说到“后续请求带的凭据”经常会遇到Token和JWT。Token是“后续请求可出示的凭据”这一类东西JWT是 Token 可能采用的一种具体数据格式。Session ID 本身也可以看成一种 Token。它只是一串随机值具体身份信息在服务端保存。所以Token 和 JWT 不是两个平级的认证方案而是“类别”和“一种具体实现”的关系。先别急着把 Token 和 JWT 当成两个对立选项。它们更像是“凭据”与“凭据格式”的关系。接下来可以从两个角度看凭据由谁保存身份信息以及服务端收到凭据后如何验证它。两种常见的 Token 设计1. 不透明 TokenOpaque Token客户端: r4nd0m-long-secret 服务端: token - { userId: alice, expiresAt, scopes }不透明 Token 的结构本身没有业务意义。它和 Session ID 很像服务端需要通过 Token 查询状态才能知道它代表谁、有没有过期、能做什么。优点是服务端可以随时吊销它代价是每次验证通常都需要查状态。2. JWT客户端: header.payload.signature 服务端: 验签并校验声明 - 读取受信任的声明JWT 的 Payload 可以包含例如{ sub: hzh, exp: 12345678910, scope: orders:read }服务端验证 JWT 时除了验签还需要检查允许的签名算法以及exp、iss、aud等声明是否符合预期。全部通过后服务端才能信任其中的身份和权限信息。签名能证明这些声明是持有对应密钥的一方签发的且传输途中没有被篡改。但必须注意JWT 的Base64URL 编码不是加密。普通签名 JWT 的内容拿到它的人通常都能解码查看。签名提供的是完整性和来源验证不是保密性。所以不要把密码、银行卡号等特别敏感的信息放进 JWT Payload。JWT 也不是天然“无状态”或更安全如果要立刻吊销某个 JWT、强制用户下线服务端通常仍需要维护黑名单、版本号或其他状态。它一旦被窃取也可能在过期前被冒用。Cookie 和 Token 并不冲突Cookie 和 Token 并非互斥关系它们解决的问题不同Cookie / Authorization Header凭据怎样从客户端到服务端。Session ID / Opaque Token / JWT凭据具体是什么以及服务端怎样验证它。例如JWT 可以放在AuthorizationHeader 中也可以放在 Cookie 中Session ID 通常放在 Cookie 中。选择哪种方式时还要结合浏览器自动携带 Cookie、CSRF 风险、XSS 风险和具体业务场景来判断。总结可以把整件事记成一句话认证解决“你是谁”授权解决“你能做什么”Session 或 Token 解决“后续请求如何证明它还是你”。无论选择 Cookie Session、不透明 Token 还是 JWT核心都一样让服务器能够安全地验证请求携带的凭据并据此恢复用户身份再决定是否允许这次操作。
身份验证:登录之后,服务器怎么一直认得你?
登录成功后问题才刚刚开始认证通过之后真正的问题才出现下一次 HTTP 请求到来的时候服务器怎么知道它仍然来自刚才已经认证的hzh为什么 HTTP 会有这个问题场景是这样的hzh输入账号密码登录商城服务器核验成功后返回“登录成功”。五分钟后hzh请求/orders。问题在于第二次请求在应用层面是一次独立请求。即使底层连接可能被复用服务器也不会自动知道这个请求还属于刚才登录的用户。除非请求带上某种可验证的信息证明它和第一次登录建立的身份有关。所以一个完整的机制通常是客户端提交认证材料例如密码。服务端验证认证材料。服务端签发后续请求要用的凭据。客户端在每个需要身份的请求中携带该凭据。服务端验证凭据并恢复或确认用户身份。服务端再根据身份、资源和操作判断权限。登录时完成的是“你是谁”的认证后续请求一般不需要重新输密码而是通过验证凭据来确认这个请求是否仍然代表刚才认证过的用户。换句话说认证建立了身份后续凭据维持了请求 - 身份之间可信的关联。一个可验证的凭据至少要具备三种能力身份关联能关联到hzh。可验证性攻击者不能随便编造一个值就冒充hzh。时效控制过期或退出登录后应该能够失效。Cookie Session最经典的方案那我们用什么来维持这个身份一个经典方案是Cookie Session。这里先记住一句话Cookie 负责携带Session 负责记录。Cookie 是浏览器携带数据的一种机制Session 则是服务端保存的会话状态。它们配合起来才能完成登录态的维持。一个完整的请求流程1. 登录用户提交账号密码服务端验证通过后创建一条 Session例如session_7f3...。把它和用户身份、过期时间等信息存到服务端。把 Session ID 通过Set-Cookie发给浏览器。2. 之后查看订单浏览器之后访问/orders时会自动带上 Cookie 中的sid。服务端用这个sid查找 Session找到对应用户后才知道请求来自谁。需要注意Cookie 本身不是认证机制。它只是浏览器自动携带数据的方式。Session 也不必放在单台应用内存中。有多台后端服务器时可以把 Session 放到 Redis 等共享存储否则第一次请求落到服务器 A第二次落到服务器 BB 就查不到登录状态。认证成功后应该重新生成 Session ID。否则攻击者如果提前让用户带上一个已知 Session ID就可能在用户登录后利用它冒充用户这叫会话固定攻击。Session ID 必须具有足够高的随机度。服务器不相信 Cookie 里自称的用户而是用这个随机 ID 查找自己保存的记录。所以可以做到删除服务端的 session_7f3... - 浏览器发送旧 Cookie - 服务端查不到有效会话 - 登录失效退出登录时发生什么如果用户退出登录后浏览器意外又发送了旧的sid服务端该怎么处理用户请求POST /logout携带sidsession_7f3...。服务端删除或标记session_7f3...失效。服务端通过Set-Cookie指示浏览器删除 Cookie这是辅助动作。旧sid再出现时服务端查不到有效 Session返回401 Unauthorized。真正让旧凭据失效的关键是第 2 步服务端不再认可这条 Session。浏览器是否成功删掉 Cookie不能作为唯一依赖。Token、Session 和 JWT 到底是什么关系说到“后续请求带的凭据”经常会遇到Token和JWT。Token是“后续请求可出示的凭据”这一类东西JWT是 Token 可能采用的一种具体数据格式。Session ID 本身也可以看成一种 Token。它只是一串随机值具体身份信息在服务端保存。所以Token 和 JWT 不是两个平级的认证方案而是“类别”和“一种具体实现”的关系。先别急着把 Token 和 JWT 当成两个对立选项。它们更像是“凭据”与“凭据格式”的关系。接下来可以从两个角度看凭据由谁保存身份信息以及服务端收到凭据后如何验证它。两种常见的 Token 设计1. 不透明 TokenOpaque Token客户端: r4nd0m-long-secret 服务端: token - { userId: alice, expiresAt, scopes }不透明 Token 的结构本身没有业务意义。它和 Session ID 很像服务端需要通过 Token 查询状态才能知道它代表谁、有没有过期、能做什么。优点是服务端可以随时吊销它代价是每次验证通常都需要查状态。2. JWT客户端: header.payload.signature 服务端: 验签并校验声明 - 读取受信任的声明JWT 的 Payload 可以包含例如{ sub: hzh, exp: 12345678910, scope: orders:read }服务端验证 JWT 时除了验签还需要检查允许的签名算法以及exp、iss、aud等声明是否符合预期。全部通过后服务端才能信任其中的身份和权限信息。签名能证明这些声明是持有对应密钥的一方签发的且传输途中没有被篡改。但必须注意JWT 的Base64URL 编码不是加密。普通签名 JWT 的内容拿到它的人通常都能解码查看。签名提供的是完整性和来源验证不是保密性。所以不要把密码、银行卡号等特别敏感的信息放进 JWT Payload。JWT 也不是天然“无状态”或更安全如果要立刻吊销某个 JWT、强制用户下线服务端通常仍需要维护黑名单、版本号或其他状态。它一旦被窃取也可能在过期前被冒用。Cookie 和 Token 并不冲突Cookie 和 Token 并非互斥关系它们解决的问题不同Cookie / Authorization Header凭据怎样从客户端到服务端。Session ID / Opaque Token / JWT凭据具体是什么以及服务端怎样验证它。例如JWT 可以放在AuthorizationHeader 中也可以放在 Cookie 中Session ID 通常放在 Cookie 中。选择哪种方式时还要结合浏览器自动携带 Cookie、CSRF 风险、XSS 风险和具体业务场景来判断。总结可以把整件事记成一句话认证解决“你是谁”授权解决“你能做什么”Session 或 Token 解决“后续请求如何证明它还是你”。无论选择 Cookie Session、不透明 Token 还是 JWT核心都一样让服务器能够安全地验证请求携带的凭据并据此恢复用户身份再决定是否允许这次操作。