跨子域会话共享问题:配置Cookie后仍需重复登录求助
看起来你已经走对了第一步——设置了跨子域的Cookie,而且能在b.example.com看到它,但登录状态不共享的问题通常出在验证逻辑不一致或者会话配置没全局同步上。我来帮你梳理几个关键的排查点和修复步骤:
你在登录页设置了session.cookie_domain,但这个配置需要在**所有需要处理登录状态的页面(包括a和b子域的每个页面)**开头都初始化,而不是只在登录页设置。比如:
// 在每个PHP脚本的最顶部添加 ini_set("session.cookie_domain", ".example.com"); session_start(); // 如果使用原生会话的话
如果只在登录页设置,b.example.com的脚本可能没正确识别会话域,导致即使Cookie存在,也无法关联到正确的用户状态。更稳妥的方式是在php.ini里全局配置session.cookie_domain = .example.com,避免遗漏。
你用openssl_encrypt加密了$mobile并存到Cookie,但在b.example.com验证时,必须用完全相同的解密流程,否则会解密失败,导致系统认不出用户:
- 确认加密方法(
aes-256-cbc)、密钥($key)、IV($iv)在两个子域完全一致 - 注意你存Cookie时用了
bin2hex(openssl_encrypt(...)),解密时必须先把十六进制转回二进制,再解密:
// b.example.com的解密代码示例 $cookie_value = $_COOKIE['hash'] ?? ''; $encrypted_data = hex2bin($cookie_value); // 这一步绝对不能忘! $mobile = openssl_decrypt($encrypted_data, "aes-256-cbc", 'hashkey', OPENSSL_RAW_DATA, 'DEFGHTABCIESPQXO'); if($mobile === false){ // 解密失败,说明密钥/IV不匹配,或者Cookie被篡改 header("Location: login.php"); exit; }
另外,aes-256-cbc要求密钥是32字节(256位),你当前的$key = 'hashkey'只有7字节,openssl会自动用NULL填充,但这既不安全也可能导致不同环境下的解密问题,建议换成一个32字符的随机密钥(比如'your-32-character-long-secret-key-here')。
即使Cookie能被看到,有些属性可能会影响它的发送:
- Secure属性:如果你的网站用HTTPS,需要在
setcookie里添加true作为第6个参数,确保Cookie只在HTTPS连接下发送:
setcookie($cookie_name, $cookie_value, time() + (900 * 30), "/", ".example.com", true);
- SameSite属性:如果你的子域之间是通过常规跳转访问(不是iframe或跨域请求),设置为
Lax即可;如果有跨子域的AJAX请求,可能需要设置为None(但要配合Secure属性):
setcookie($cookie_name, $cookie_value, time() + (900 * 30), "/", ".example.com", true, true); // 最后一个true是SameSite=None
- HttpOnly:这是安全属性,不影响跨子域共享,但建议加上,防止XSS窃取Cookie:
setcookie($cookie_name, $cookie_value, time() + (900 * 30), "/", ".example.com", true, true, true);
在b.example.com中,读取Cookie解密后,必须执行和a.example.com相同的用户验证逻辑:
- 解密得到
$mobile后,去数据库查询该手机号对应的用户是否存在 - 如果存在,将用户ID或登录状态存入会话(比如
$_SESSION['user_id'] = $user['id']) - 后续页面通过检查会话中的用户ID来判断是否已登录
如果b.example.com的验证逻辑跳过了数据库查询,或者解密后没有正确设置会话状态,系统会认为用户未登录,要求重新登录。
- 在
b.example.com的页面中执行var_dump($_COOKIE['hash']),确认Cookie值和a.example.com的完全一致 - 打印解密后的
$mobile,看是否能得到正确的手机号 - 检查服务器时间是否同步,如果a和b子域的服务器时间差过大,可能导致Cookie提前过期
内容的提问来源于stack exchange,提问作者Adnan Siddiqui

