【问题标题】:Check if cookies are enabled检查是否启用了 cookie
【发布时间】:2011-10-03 13:54:49
【问题描述】:

我正在处理需要 javascript 和会话的页面。如果 javascript 被禁用,我已经有代码来警告用户。现在,我想处理禁用 cookie 的情况,因为会话 id 存储在 cookie 中。

我想到了几个想法:

  1. 在链接和表单中嵌入会话 ID
  2. 警告用户,如果 cookie 被禁用,他们必须启用(需要帮助检测 cookie 是否被禁用)

解决此问题的最佳方法是什么?谢谢

编辑

根据链接的文章,我想出了自己的方法,并认为我会分享,其他人也许可以使用它,也许我会得到一些批评。 (假设您的 PHP 会话存储在名为 PHPSESSID 的 cookie 中)

<div id="form" style="display:none">Content goes here</div>
<noscript>Sorry, but Javascript is required</noscript>
<script type="text/javascript"><!--
if(document.cookie.indexOf('PHPSESSID')!=-1)
   document.getElementById('form').style.display='';
else
   document.write('<p>Sorry, but cookies must be enabled</p>');
--></script>

【问题讨论】:

  • 在链接中嵌入会话 id 是可能的,但很麻烦。这意味着您正在向搜索引擎提供会话 ID。这意味着共享链接的人可以登录到同一个会话。
  • 您能否将问题的标题更新为:Check if cookies are enabled with javascript ?
  • 这不是问题的内容,请阅读整个问题。 JavaScript 就是这个问题的答案。

标签: php javascript session-cookies


【解决方案1】:

JavaScript

在 JavaScript 中,您可以简单地测试 cookieEnabled 属性,所有主流浏览器都支持该属性。如果您使用较旧的浏览器,您可以设置一个 cookie 并检查它是否存在。 (借自Modernizer):

if (navigator.cookieEnabled) return true;

// set and read cookie
document.cookie = "cookietest=1";
var ret = document.cookie.indexOf("cookietest=") != -1;

// delete cookie
document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";

return ret;

PHP

在 PHP 中它相当“复杂”,因为您必须刷新页面或重定向到另一个脚本。这里我将使用两个脚本:

somescript.php

<?php
session_start();
setcookie('foo', 'bar', time()+3600);
header("location: check.php");

check.php

<?php echo (isset($_COOKIE['foo']) && $_COOKIE['foo']=='bar') ? 'enabled' : 'disabled';

【讨论】:

  • 如果您可以扩展您的答案以解释这些链接另一端的一些技术并保留links for reference,那将非常有帮助。如果不这样做,答案就会面临链接失效的风险,而这些类型的链接通常会突然消失。谢谢。
  • 不需要重定向,另请参阅下面的答案。您无需“重新加载”即可检查 cookie 是否已启用。
  • 第二个链接中有恶意软件吗? “PHP 和 Cookies,一个很好的组合!”为什么它要我安装一个令人毛骨悚然的浏览器扩展?
  • @MiguelValencia:该网站似乎已不存在,我已删除链接
  • 感谢您简洁明了的回答。 Modernizer 现在建议不要使用 navigator.cookieenabled:github.com/Modernizr/Modernizr/blob/master/feature-detects/…
【解决方案2】:

但是要检查是否使用 isset($_COOKIE["cookie"]) 启用了 cookie,您必须刷新。 我是这样做的(基于 cookie 的会话 :)

session_start();
$a = session_id();
session_destroy();

session_start();
$b = session_id();
session_destroy();

if ($a == $b)
    echo"Cookies ON";
else
    echo"Cookies OFF";

【讨论】:

  • 这是迄今为止最简单最好的例子!一条评论:在执行此操作之前首先检查会话是否已启动,并在完成测试时保持启用状态。
  • 在此页面上查看我修改后的更强大的答案!
  • 刷新后才有效!在第一次加载时,它总是显示 Cookies OFF,因为在不与浏览器交换至少一个请求的情况下,无法测试是否启用了 cookie。 Cookie 是每个请求的标头信息的一部分,Cookie 操作是通过响应标头完成的。没有办法解决它。
【解决方案3】:

回答一个老问题,这个新帖子发布于 2013 年 4 月 4 日

为了完成@misza 的回答,这里有一个高级方法来检查是否在不重新加载页面的情况下启用了cookie。 @misza 的问题在于,当 php ini 设置 session.use_cookies 不正确时,它并不总是有效。此外,该解决方案不会检查会话是否已启动。

我做了这个功能,并在不同的情况下对其进行了多次测试,并且做得很好。

    function suGetClientCookiesEnabled() // Test if browser has cookies enabled
    {
      // Avoid overhead, if already tested, return it
      if( defined( 'SU_CLIENT_COOKIES_ENABLED' ))
       { return SU_CLIENT_COOKIES_ENABLED; }

      $bIni = ini_get( 'session.use_cookies' ); 
      ini_set( 'session.use_cookies', 1 ); 

      $a = session_id();
      $bWasStarted = ( is_string( $a ) && strlen( $a ));
      if( !$bWasStarted )
      {
        @session_start();
        $a = session_id();
      }

   // Make a copy of current session data
  $aSesDat = (isset( $_SESSION ))?$_SESSION:array();
   // Now we destroy the session and we lost the data but not the session id 
   // when cookies are enabled. We restore the data later. 
  @session_destroy(); 
   // Restart it
  @session_start();

   // Restore copy
  $_SESSION = $aSesDat;

   // If no cookies are enabled, the session differs from first session start
  $b = session_id();
  if( !$bWasStarted )
   { // If not was started, write data to the session container to avoid data loss
     @session_write_close(); 
   }

   // When no cookies are enabled, $a and $b are not the same
  $b = ($a === $b);
  define( 'SU_CLIENT_COOKIES_ENABLED', $b );

  if( !$bIni )
   { @ini_set( 'session.use_cookies', 0 ); }

  //echo $b?'1':'0';
  return $b;
    }

用法:

if( suGetClientCookiesEnabled())
 { echo 'Cookies are enabled!'; }
else { echo 'Cookies are NOT enabled!'; }

重要提示: 该功能在PHP的ini设置不正确时临时修改,未启用时恢复。这只是为了测试是否启用了 cookie。当您启动会话并且 php ini 设置 session.use_cookies 的值不正确时,它可能会出错。为确保会话正常工作,请在开始会话之前检查和/或设置它,例如:

   if( suGetClientCookiesEnabled())
     { 
       echo 'Cookies are enabled!'; 
       ini_set( 'session.use_cookies', 1 ); 
       echo 'Starting session';
       @start_session(); 

     }
    else { echo 'Cookies are NOT enabled!'; }

【讨论】:

  • Erwinus,您能否解释一下您所说的“启动会话时可能会出错并且 php ini 设置 session.use_cookies 的值不正确”是什么意思。什么值可能不正确?我正在尝试实现您的想法,但不确定我需要将我的 php ini 设置为...谢谢!
  • @Sebastian:当您在检查 cookie 是否启用并且 session.use_cookies 为 FALSE 之前启动会话时,它可能会失败。为了确保它正常工作,您必须在开始任何会话之前首先调用测试函数 suGetClientCookiesEnabled()。这对您/您来说清楚/可以理解吗?希望对您有所帮助。
  • 不幸的是,它在第​​一次调用站点时不起作用,例如尝试隐身模式。 第一次调用站点后,您可以期望设置 $_COOKIE['PHPSESSID'] 并证明 cookie 已启用,但在第一次调用时它是空的 - 使用您的方法仍然每次都得到一个新的会话 id,这并不能证明什么。
  • @Rob:我认为你做错了什么。在开始任何其他会话之前,您必须检查 cookie 是否已启用。另请参阅对塞巴斯蒂安的评论和答案中的“重要说明”。出于安全原因,最好重命名会话名称: ini_set( 'session.name', 'your name' ) 和 ini_set( 'session.use_only_cookies', true );和 ini_set('session.use_trans_sid', false);
  • @Erwinus - 你没试过吗?为了证明我所说的,请尝试: 1. 使用您的答案中的代码创建一个 php 文件 2. 在 chrome 中打开一个新的 incognito window 3. 直接浏览到 php 测试文件。第一个电话说:“未启用 Cookie!”。第二个电话说:“启用了 Cookie!”。我只是指出这一点。不幸的是,它使您的代码有点浪费时间,因为在第二次调用时,您可以检查是否填充了 $_COOKIE['PHPSESSID'] - 如果是,则启用 cookie。
【解决方案4】:

一种透明、干净和简单的方法,使用 PHP 检查 cookie 可用性并利用 AJAX 透明重定向,因此 不会触发页面重新加载。它也不需要会话。

客户端代码 (JavaScript)

function showCookiesMessage(cookiesEnabled) {
    if (cookiesEnabled == 'true')
        alert('Cookies enabled');
    else
        alert('Cookies disabled');
}

$(document).ready(function() {
    var jqxhr = $.get('/cookiesEnabled.php');
    jqxhr.done(showCookiesMessage);
});

(JQuery AJAX 调用可以替换为纯 JavaScript AJAX 调用)

服务器端代码 (PHP)

if (isset($_COOKIE['cookieCheck'])) {
    echo 'true';
} else {
    if (isset($_GET['reload'])) {
        echo 'false';
    } else {
        setcookie('cookieCheck', '1', time() + 60);
        header('Location: ' . $_SERVER['PHP_SELF'] . '?reload');
        exit();
    }
}

第一次调用脚本时,cookie 被设置并且脚本告诉浏览器重定向到它自己。浏览器透明地执行它。 不会发生页面重新加载,因为它是在 AJAX 调用范围内完成的

第二次通过重定向调用时,如果接收到 cookie,脚本会响应 HTTP 200(字符串为“true”),因此会调用 showCookiesMessage 函数。

如果第二次调用脚本(由“reload”参数标识)并且未接收到 cookie,它会使用字符串“false”响应 HTTP 200 - 并调用 showCookiesMessage 函数。

【讨论】:

  • 这种方法适用于大多数设备,但如果禁用 javascript 则会变得疯狂
【解决方案5】:

你不能在同一个页面的加载集中检查是否设置了cookies你必须执行重新加载页面:

  • PHP 在服务器上运行;
  • 客户端的 cookie。
  • cookies 仅在页面加载期间发送到服务器。
  • 刚刚创建的 cookie 尚未发送到服务器,只会在下次加载页面时发送。

【讨论】:

  • 有可能,看我的回答
  • 谢谢 Martijn。我只是在学习并欣赏这种构象。由于您的第一点,我发现能够在 PHP 脚本中设置或读取 cookie 的整个想法非常令人困惑。按照 PHP 手册,您会认为只要在 标记之前执行 setcookie(),就可以在稍后立即阅读一行代码,这似乎几乎不可能我,除非我错过了一些重要的东西。坦率地说,你最后一点发生的机制对我来说仍然是个谜。我希望我能找到有关其工作原理的明确解释。
【解决方案6】:

您可以进行 Ajax 调用(注意:此解决方案需要 JQuery):

example.php

<?php
    setcookie('CookieEnabledTest', 'check', time()+3600);
?>

<script type="text/javascript">

    CookieCheck();

    function CookieCheck()
    {
        $.post
        (
            'ajax.php',
            {
                cmd: 'cookieCheck'
            },
            function (returned_data, status)
            {
                if (status === "success")
                {
                    if (returned_data === "enabled")
                    {
                        alert ("Cookies are activated.");
                    }
                    else
                    {
                        alert ("Cookies are not activated.");
                    }
                }
            }
        );
    }
</script>

ajax.php

$cmd = filter_input(INPUT_POST, "cmd");

if ( isset( $cmd ) && $cmd == "cookieCheck" )
{
    echo (isset($_COOKIE['CookieEnabledTest']) && $_COOKIE['CookieEnabledTest']=='check') ? 'enabled' : 'disabled';
}

结果会出现一个警告框,显示是否启用了 cookie。当然您不必显示警告框,从这里您可以采取其他步骤来处理停用的 cookie。

【讨论】:

    【解决方案7】:

    JavaScript

    您可以使用 JavaScript 创建一个 cookie 并检查它是否存在:

    //Set a Cookie`
    document.cookie="testcookie"`
    
    //Check if cookie exists`
    cookiesEnabled=(document.cookie.indexOf("testcookie")!=-1)? true : false`
    

    或者你可以使用jQuery Cookie plugin

    //Set a Cookie`
    $.cookie("testcookie", "testvalue")
    
    //Check if cookie exists`
    cookiesEnabled=( $.cookie("testcookie") ) ? true : false`
    

    PHP

    setcookie("testcookie", "testvalue");
    
    if( isset( $_COOKIE['testcookie'] ) ) {
    
    }
    

    不确定Php是否可以工作,因为我无法对其进行测试。

    【讨论】:

    • PHP 代码不起作用。您需要重新加载页面,以便浏览器发送第二个 HTTP 请求。如果第二个 HTTP 请求具有从第一个 HTTP 请求设置的 cookie,则启用 cookie。
    【解决方案8】:

    很容易检测cookies是否启用:

    1. 设置 cookie。
    2. 获取 cookie

    如果你能得到你设置的cookie,则cookie是启用的,否则不是。

    顺便说一句:Embedding the session id in the links and forms 是个坏主意,对 SEO 不利。 在我看来,人们不想启用 cookie不是很常见

    【讨论】:

    • 仅供参考,您实际上会感到惊讶。我有一个 Firefox 插件,它可以阻止除白名单上的域以外的所有 cookie,并且注意到许多用户都效仿。事实上,这就是引发问题的原因:我无法使用表单,一开始也不知道为什么,哈哈。
    • 不能使用表格是什么意思?无法将 jsessionid 嵌入到表单中?
    • 表单是一个多提交系统,没有启用 cookie,页面一直从头开始而不是继续,因为会话永远无法设置。
    • 在欧洲有一个新的 cookie 法,它害怕很多人启用 cookie,因为网站必须要求接受 cookie。这个问题激怒了访问者,因此他们完全关闭了 cookie。你说:“不是很常见”,这是真的,因为他们不知道它的存在。由于这条愚蠢的法律,更多的人知道它并在他们知道该怎么做时将其关闭。
    【解决方案9】:

    这是一个非常有用且轻量级的 javascript 插件来完成此操作:js-cookie

    Cookies.set('cookieName', 'Value');
          setTimeout(function(){
            var cookieValue =  Cookies.get('cookieName');
            if(cookieValue){
               console.log("Test Cookie is set!");
            } else {
               document.write('<p>Sorry, but cookies must be enabled</p>');
            }
            Cookies.remove('cookieName');
          }, 1000);
    

    适用于所有浏览器,接受任何字符。

    【讨论】:

      【解决方案10】:

      Cookie 是客户端的,无法使用 PHP 正确测试。 这是基线,每个解决方案都是针对这个问题的一个总结。

      意思是,如果您正在寻找 cookie 问题的解决方案,那么您就走错了路。不要使用 PHP,使用 Javascript 之类的客户端语言。

      您可以通过 PHP 使用 cookie 吗?是的,但您必须重新加载才能使 PHP 的设置“可见”。

      例如:是否可以测试浏览器是否可以使用纯 PHP 设置 Cookie。唯一正确的答案是“否”。

      您能否读取已设置的 Cookie:“是”使用预定义的 $_COOKIE(启动 PHP-App 之前的设置副本)。

      【讨论】:

        猜你喜欢
        • 2011-04-02
        • 2012-02-26
        • 1970-01-01
        • 1970-01-01
        • 2012-03-15
        • 2012-03-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多