飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

答案:Cookie与Session状态管理

问题: 波比(活动运营)在飞翔官网www.feixiang.net登录后,发现访问hr.feixiang.net时也需要重新登录。请分析原因,并说明如何通过Cookie的Domain属性解决这个问题。

答案:

原因分析

云吞(安全工程师)向波比解释道:这是Cookie的Domain匹配规则导致的。

当波比在www.feixiang.net登录时,服务器设置的Cookie默认Domain属性为www.feixiang.net。根据浏览器的同源策略,Cookie只能被发送到完全匹配的域名或其子域名(当Domain属性显式设置时)。

# 登录响应头(默认情况)
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure

# 浏览器存储的Cookie Domain为 www.feixiang.net

浏览器发送Cookie的规则是:

  • 访问www.feixiang.net → Cookie会带上 ✅
  • 访问hr.feixiang.net → Cookie不会带上 ❌
  • 访问api.feixiang.net → Cookie不会带上 ❌

因为hr.feixiang.net和www.feixiang.net是同级子域名,不是包含关系,所以Cookie无法共享。

解决方案:设置Domain属性为.feixiang.net

靓晴(UI设计)和凌叔(架构师)讨论后,决定通过显式设置Cookie的Domain属性来实现跨子域名共享登录状态。

将Domain设置为.feixiang.net(注意前面的点,现代浏览器会自动处理),这样该Cookie对feixiang.net及其所有子域名都有效。

# 修改后的登录响应头
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Domain=.feixiang.net; Path=/; HttpOnly; Secure; SameSite=Lax

设置后,浏览器在以下域名都会自动带上Cookie:

  • www.feixiang.net ✅
  • hr.feixiang.net ✅
  • api.feixiang.net ✅
  • admin.feixiang.net ✅

飞翔公司的完整实现

鸣哥(DevOps)在飞翔官网的登录服务中做了如下配置:

# Python Flask 示例
from flask import Flask, make_response

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    # 验证用户名密码...
    session_id = create_session(user_id)
    
    resp = make_response({'code': 0, 'msg': '登录成功'})
    resp.set_cookie(
        'session_id', 
        session_id,
        domain='.feixiang.net',      # 关键:共享给所有子域名
        path='/',
        httponly=True,                # 防止XSS窃取
        secure=True,                  # 仅HTTPS传输
        samesite='Lax',               # 防止CSRF攻击
        max_age=86400 * 7             # 7天有效期
    )
    return resp
// Node.js Express 示例
const express = require('express');
const app = express();

app.post('/login', (req, res) => {
    const sessionId = createSession(req.body.userId);
    
    res.cookie('session_id', sessionId, {
        domain: '.feixiang.net',      // 关键:共享给所有子域名
        path: '/',
        httpOnly: true,
        secure: true,
        sameSite: 'lax',
        maxAge: 86400 * 7 * 1000     // 7天(毫秒)
    });
    
    res.json({ code: 0, msg: '登录成功' });
});

安全注意事项

云吞特别提醒:

  1. 不要设置Domain为顶级域名(如.com、.cn),这会导致Cookie被发送到该顶级域下的所有网站,存在严重安全隐患。

  2. 配合HttpOnly和Secure:防止JavaScript读取Cookie(XSS防护)和确保只在HTTPS下传输。

  3. SameSite属性:设置为Lax或Strict,防止跨站请求伪造(CSRF)攻击。

  4. Session集中存储:使用Redis等集中式Session存储,确保各子域名都能验证Session有效性。

# 查看浏览器中的Cookie(开发者工具控制台)
document.cookie
# 输出:"session_id=abc123" (如果设置了HttpOnly则不可见)

# 在Network面板中查看请求头
Cookie: session_id=abc123

修改后,波比在www.feixiang.net登录后,访问hr.feixiang.net、 admin.feixiang.net等子域名时都能自动保持登录状态,无需重复输入密码,工作效率大大提升。