上传到实时服务器后,setcookie 不起作用

Posted

技术标签:

【中文标题】上传到实时服务器后,setcookie 不起作用【英文标题】:setcookie is not working after uploaded to live server 【发布时间】:2021-11-24 15:20:56 【问题描述】:

我在 php 中使用 setcookie 来检查访问我网站的用户。问题是当我在我的本地服务器上测试它时它可以工作,cookie 被设置但是当我在 cpanel 中上传页面时,cookie 没有被设置。 以下是我的代码概要:

<?php
session_start();
//set the cookie time to desired value;
setcookie("user", "abc", time()+3600);
//some other codes

if(!isset($_COOKIE["user"]))

//some other codes

?>

任何帮助将不胜感激。谢谢

【问题讨论】:

setcookie() 函数会将一些 HTTP 标头添加到您的响应中,以便您的浏览器存储一个名为“user”的 cookie。当您还启动了一个会话时,它还会要求您的浏览器存储另一个名为“PHPSESSID”的 cookie。 $_COOKIE 数组在第一个页面加载时为空,因为您的浏览器在第一次访问之前没有它们。如果你进入浏览器检查器,你应该找到它们。现在,如果您重新加载页面,浏览器将在请求中发送这些 cookie,然后它们将显示在 var_export($_COOKIE) 中。检查 HTTP 标头是否正确。 现在,我有一个问题:您需要设置另一个cookie“用户”的原因是什么?为什么不将它存储在 PHP 会话数组 $_SESSION 中?解释您正在尝试做什么可能会很有趣,因为我们可以帮助您找到解决问题的最佳方法。 它在我的本地系统上工作,但我在服务器上遇到问题 cookie 没有设置任何解决方案! 我为用户设置了 cookie,即使在浏览器窗口像所有社交媒体网站一样关闭后也能登录 然后检查 HTTP 响应,看看是否有 Set-Cookie: user=abc; expires=Mon, 04-Oct-2021 07:53:39 GMT; Max-Age=3600 标头。如果它丢失了,那么好的,你的服务器有一个特定的配置或禁用的东西。 【参考方案1】:

关于我在 cmets 中的问题的答案,您可能只需要修改会话的 cookie 生命周期,而不是创建另一个“用户”cookie。

// TTL (Time To Live) of the cookie stored in the browser.
ini_set('session.cookie_lifetime', 432000); // 5 days

// On the server side, the garbage collector should delete
// old sessions too, after the same TTL.
ini_set('session.gc_maxlifetime', 432000); // 5 days

// Fire the garbage collector only every 100 requests.
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

在代码的开头执行此操作,通常在应用程序引导程序中包含的 config.php 文件中。

你可以看到更多in the PHP session configuration。

关于生命周期有一个小问题:cookie 会在生命周期设置后过期,但是由于 cookie 是创建的,所以在你第一次登录时发起会话的那一刻。

通常,您希望 cookie 的生命周期从最后一个用户的操作开始。您可以通过更新 cookie 来做到这一点,以便 PHP 重新发送 Cookie HTTP 标头以覆盖它。我还添加了一些其他应该在 PHP 会话中进行的安全设置。所有内容都在下面的运行示例中进行了注释:

<?php

/**
 * Testing PHP cookie settings and improve security.
 */

// The cookie lifetime in seconds.
define('COOKIE_LIFETIME', 10);

// Simulate user's data from the database.
$user_mail = 'james.bond@gmail.com';
// A salt per user is good. It avoids an attacker to be able
// to calculate the session cookie name himself if he discovers that
// it is just done by hashing the user's e-mail.
$user_salt = 'nbVzr432';

// Detect if we are over HTTPS or not. Needs improvement if behind a SSL reverse-proxy.
// It's just used for the cookie secure option to make this POC work everywhere.
$is_https = isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']);

// On the PHP server side, the garbage collector should delete
// old sessions after the same lifetime value.
ini_set('session.gc_maxlifetime', COOKIE_LIFETIME);

// Fire the garbage collector only every 100 requests to save CPU.
// On some OS this is done by a cron job so it could be commented.
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

// Improve some session settings:
ini_set('session.use_cookies ', 1);
ini_set('session.use_only_cookies  ', 1);
ini_set('session.use_strict_mode ', 1);

// This POC will just print some plain text.
header('Content-Type: text/plain; charset=utf-8');

// Change the session cookie name so that an attacker cannot find it.
$session_cookie_name = 'SESS_' . sha1($user_mail . $user_salt);
// Store all the session cookie options in an array.
$session_cookie_options = [
    // Set the cookie lifetime (the browser sets an expire to delete it automatically).
    'lifetime' => COOKIE_LIFETIME,
    // The cookie path defines under which relative URL the cookie should be sent.
    // If your app is running under https://your-site.com/shop/ then the cookie path
    // should be set to /shop/ instead of the default / as there's no reason to send
    // your shop's session cookie to another app running at https://your-site.com/forum/.
    'path' => '/',
    // Cookie domain. Use null to let PHP handle that. But if you want a session
    // cookie accross multiple sub-domains such as forum.your-site.com and shop.your-site.com
    // then you should set the domain to ".your-site.com".
    'domain' => null,
    // If we are in HTTPS then don't let cookies be sent over HTTP.
    // Here I used $is_https to make it run everywhere but if you have
    // HTTPS on your domain then replace it by 1 to lock it!
    'secure' => $is_https ? 1 : 0, // IMPORTANT: Replace by 1 if you have both HTTP and HTTPS enabled.
    // Don't let javascript access the session cookie.
    'httponly' => 1,
    // If another site has a link pointing to your website then don't send
    // the session cookie (POST or GET). This mitigates somes kind of attacks.
    'samesite' => 'Strict',
];

// Apply all the session cookie settings without ini_set() for maximum portability:
session_name($session_cookie_name);
session_set_cookie_params($session_cookie_options); // Since PHP 7.3 only
session_start();

// If the session cookie has been sent by the browser then it might have an expiration
// date to early (because it is set only once at the creation of the session).
// Instead we would like it to expire with our lifetime since the last user's
// action. To do that we have to use setcookie() to resend the cookie in order
// to update/overwrite it to have a new expiration date in the browser.
if (isset($_COOKIE[$session_cookie_name]) && $_COOKIE[$session_cookie_name] == session_id()) 
    $cookie_options = $session_cookie_options;
    unset($cookie_options['lifetime']); // This one is replaced by expires below.
    $cookie_options['expires'] = time() + COOKIE_LIFETIME;
    setcookie($session_cookie_name, session_id(), $cookie_options);


// Now that HTTP headers have been set, we are allowed to start printing output.

// If the user is already logged and his caddie is empty then fill it with some
// random stuff. It will stay saved until the session expires.
if (isset($_SESSION['session_creation_date']) && !isset($_SESSION['shop_caddie'])) 
    $_SESSION['shop_caddie'] = [
        'T-shirt' => [
            'quantity' => rand(1, 3),
            'color' => 'red',
        ],
        'Beer' => [
            'quantity' => (['2dl', '3dl', '5dl'])[rand(0, 2)],
        ]
    ];


// If the session is empty, let's init it with the creation date for the showcase.
if (empty($_SESSION)) 
    $_SESSION['session_creation_date'] = date('r');


print 'Recieved cookies from the browser = ' . var_export($_COOKIE, true) . "\n\n";
print 'Session data = ' . var_export($_SESSION, true) . "\n\n";

【讨论】:

以上是关于上传到实时服务器后,setcookie 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

mPDF实时上传不起作用

上传到服务器后不允许英特尔 XDK Ajax 访问 [在 xampp 中运行良好]

主机上传后 CSS 图标不起作用

Laravel - CSRF 与会话令牌不匹配

cookie不能在10秒后过期

使用 Alamofire 将图像上传到服务器不起作用