【问题标题】:Shopping cart persistence: $_SESSION or browser cookie?购物车持久性:$_SESSION 还是浏览器 cookie?
【发布时间】:2012-09-16 04:20:05
【问题描述】:

在没有用户名/登录名来保存购物车数据的电子商务网站上,使用 PHP $_SESSION 变量还是浏览器 cookie 来保存购物车中的商品会更好吗?我倾向于 $_SESSION,因为 cookie 可以被禁用,但想听听你的想法。

提前感谢您的考虑。

【问题讨论】:

  • 如果两者都做呢? $_SESSION 的缺点是当浏览器关闭时会话被清除。使用会话,但尝试从 cookie 填充 $_SESSION 数据(如果可用)。
  • @Travesty3 你应该添加这个作为答案。
  • 按照@Travesty3 所说的去做,只要记住:不要在 cookie 中存储敏感信息。它们一直在从浏览器到服务器来回移动,很容易被嗅探或黑客攻击。
  • @xPheRe:认为您的意思是“敏感”信息;-)
  • 将其存储在会话中是安全,因此很好,但@Xeoncross 解释了为什么仅将唯一 ID 存储在会话并将实际数据存储在您的数据库中。

标签: php cookies session-variables


【解决方案1】:

我会将其存储在 SESSION 中。我的愿望清单比较长,我怕它不适合COOKIE可能占用的4K存储空间。它会强制您将会话超时设置为更长的时间。

注意:有些国家(比如我所在的荷兰)对 cookie 有非常严格的政策,您可能会被立法强制使用 Sessions。

【讨论】:

  • 如果您只是存储项目 ID 和数量值怎么办?
  • 你从来没见过我老婆逛街!
【解决方案2】:

一些帮助点:

Cookie:

  • 信息会一直保留到 cookie 过期(您可以配置什么);
  • 往往会减慢服务器和客户端之间的通信,因为它必须在每个请求/响应中在两者之间进行交换;
  • 它是一种不安全的数据存储形式,并且易于嗅探;
  • 它们也有存储数据的限制。

会话:

  • 所有信息都保存在服务器中,因此不会与客户端交换。
  • 因为它不是跨网络共享的,所以更安全一些;
  • 会话结束时所有信息都会丢失;
  • 如果您在共享主机中托管,您可能会遇到会话在操作过程中结束的问题,因为同一服务器上托管的任何站点都会推送资源。

我会亲自参加会议,因为我假设是一个中小型受众页面。如果它增长,您最好使用简单的数据库结构来存储这些数据,并制定维护计划来获取不必要的数据(例如:选择某些产品但不进行结帐的客户)。

【讨论】:

  • "如果您有很多访问者,您的服务器会普遍变慢,因为存储所有会话变量所需的 RAM 量;" ——我不认为这是一个准确的说法。会话数据不会存储在 RAM 中,除非您实现了明确这样做的自定义会话处理程序。即使在这种情况下,您也可能正在使用诸如专用的 memcached 服务器之类的东西,它会预先分配一定数量的 RAM。
  • 好的,你说得对。我假设了一些其他的技术,可能又被我误会了,但是作为经典的 ASP 等等。我会删除那句话。
【解决方案3】:

我会使用会话。如果用户禁用了 cookie,则会话将无法启动,因为会话 ID 存储在用户计算机上的 cookie 中。

您可能需要查看一些设置,以便尝试将会话保持更长时间。

  • 通过运行带有lifetime 参数集的session_set_cookie_params(),防止会话cookie 在用户关闭浏览器时被删除。该函数需要在session_start()之前运行

  • 您可能还希望通过在 php.ini 中或使用 ini_set() 修改会话垃圾收集设置 session.gc_probability, session.gc_divisor, session.gc_maxlifetime 来延长从服务器清除会话的频率

  • 1234563还可以通过修改session_save_path() 将这些会话保存到与其他网站不同的目录。这又在session_start() 之前运行。这将防止其他网站的垃圾收集清除您对某个特定网站的扩展会话。
  • 我还建议在 php.ini session.entropy_file = /dev/urandom, session.entropy_length = 256, session.hash_function = sha512 中设置以下会话设置。这应该会为您提供一个加密性强的会话 ID,并且冲突的可能性极小。

  • 并确保您的站点上有 SSL 证书,以防止中间人攻击您的会话 ID。

显然,用户仍然可以决定手动清除他们所有的 cookie,这些 cookie 将带走会话 ID cookie,但这是我准备承担的风险。如果我在购物车系统中途没有结账,我就不会去清除我的 cookie。我仍然认为会话比仅使用普通 cookie 更好。

只要您是唯一可以访问您的会话目录并且您的会话 ID 很强大的网站,数据就足够安全。通过延长服务器的会话存储时间,您的数据可以保留在服务器上。

您可以采取进一步的措施来使您的会话更加强大。每 20 分钟重新生成一次会话 ID,复制数据。还要在数据库中根据 IP 地址记录会话 ID,并检查特定 IP 地址是否尝试在给定时间内发送超过 X 个会话 ID,以防止有人尝试暴力破解会话 ID。

您还可以将数据存储在由会话 ID 链接的数据库中,而不是存储在服务器上的会话文件中。然而,这仍然依赖于存储在 cookie 中并且可能随时消失的会话 ID。真正确保用户不会丢失购物车的唯一方法是让他们先登录并存储在数据库中。

【讨论】:

  • 虽然我说 PHP 会话需要 cookie,但这在技术上是不正确的。会话 ID 可以作为 URL 中的 GET 变量在页面之间传输。但是,您真的不想考虑该选项 - 它不一致且通常令人讨厌且不推荐。
【解决方案4】:

你可以考虑同时使用。

$_SESSION 的缺点是当浏览器关闭时会话被清除。

使用会话,但尝试从 cookie 填充 $_SESSION 数据(如果可用)。

【讨论】:

    【解决方案5】:

    都没有

    没有大型网站敢将用户的购物车存储在会话或 cookie 中 - 这些数据非常有价值。

    客户在购买什么、何时选择商品、购买了多少、为什么他们没有完成结账等等。这些对您的业务非常非常非常重要。

    使用数据库表来存储这些信息,然后将其链接到用户的会话。这样您就不会丢失信息,并且可以返回并根据用户购物车构建统计数据或解决结帐过程中的问题。

    尽可能记录一切。

    数据库架构

    下面是一个简化的示例,说明这在数据库级别的外观。

    user {
        id
        email
    }
    
    product {
        id
        name
        price
    }
    
    cart {
        id
        product_id
        user_id
        quantity
        timestamp    (when was it created?)
        expired      (is this cart still active?)
    }
    

    您可能还希望将购物车表拆分为更多表,以便跟踪对购物车的修订。

    会话

    普通的 PHP 会话由两部分组成

    1. 数据(存储在服务器上的文件中)
    2. 为用户代理(浏览器)提供的唯一标识符

    因此,这不是 $_SESSION$_COOKIE - 它是 $_SESSION + $_COOKIE = "session"。但是,您可以通过使用包含数据的单个加密 cookie 来修改它(因此您不需要标识符来查找数据)。另一种常见的方法是将数据存储在 memcached 或数据库中而不是文件系统中,以便多个服务器可以访问它。

    @Travesty3 的意思是您可以拥有 两个 cookie - 一个用于会话,另一个是“让我保持登录”cookie(比会话 cookie 存在的时间更长) , 或单独 cookie 中的数据副本。

    【讨论】:

    • 这是一个有趣的方法。但是,我应该指出,听起来您的回答仍然支持 $_SESSION。
    • $_SESSION 需要匹配的$_COOKIE,所以这并不重要。实际上,我的大部分内容都使用了加密 cookie,并跳过了 file/database/memcached $_SESSION 包装器,因为我的 cookie 中只有几个小数据点,例如 user_id。
    • 我用示例架构更新了我的答案。会话与购物车无关。会话只是为了知道哪个用户正在与您的应用交互 - 一旦您知道您将 user_id 用于其他所有事情。
    • @nodirtyrockstar,你也可以这样做。然后,当会话过期时,购物车会自动以某种方式“禁用”,因为没有人会再有任何引用它。但是,可能会在一段时间内创建两个 session_id 匹配 - 因此,如果您在数据库中使用它,您可能希望在它前面加上一些前缀。
    • 我认为这个答案更多的是对企业的政策,而不是对技术问题的回答。您可以在回答其技术性之后提出替代方案。
    【解决方案6】:

    正如 Xeoncross 所指出的,存储任何可能的信息以供分析是非常重要的。因此,不应完全依赖会话和 cookie。

    一种可能的方法是-

    未登录时使用会话

    如果用户未登录,您可以使用 PHP 中的$_SESSION 从会话中存储和检索购物车项目和愿望清单项目

    登录时使用数据库

    如果用户已登录,那么您可以考虑以下两个选项之一 -

    • 将购物车项目或愿望清单项目单独存储在数据库中
    • 将购物车项目或愿望清单项目存储在数据库以及会话中(这将保存您的一些数据库查询)

    用户登录时

    当用户登录时,从会话中获取所有购物车项目和愿望清单项目并将其存储在数据库中。

    这将使数据持久化,即使用户注销或更改机器但直到用户没有登录,都无法永久存储信息,因此不会持久化。

    获取所需数据

    当您尝试访问购物车或愿望清单时,请执行以下检查 -

    • 如果用户未登录,则查看会话
    • 如果用户已登录,如果您单独存储在数据库中,则查询数据库,否则如果您与数据库一起保持会话更新,则可以只查看会话

    【讨论】:

    • 我知道这篇文章已经有一年多了,但我还有一个问题。如果用户在数据库中创建一个购物车,然后在会话中创建另一个购物车(可能在不同的机器上)然后登录怎么办?我认为覆盖数据库中的当前数据不是一个好主意,但是忽略新的会话购物车也不是一个选择。在这种情况下,最好的解决方案是什么?
    • @user2988879 我认为存在误解。当用户登录时,我们不会覆盖数据库中的当前数据。它只是在购物车中添加新项目。除非用户从购物车中删除(移除),否则这些新商品将存在于现有商品之外。
    • 在某些情况下是不是有点奇怪?例如:用户在他们的帐户上创建了一个购物车,然后在另一台 PC 上创建了一个购物车而没有登录。然后用户想用新的购物车结账,所以他们登录了。购物车被添加在一起,用户首先必须删除他们第一次添加的所有产品,然后才能使用新购物车结帐。
    • 好吧,在这种情况下,您可以在您的数据库中为购物车表保留一个标志,该标志将决定是否要签出产品。然后,如果用户签出某些项目并登录,则将已存在项目的标志标记为 false,将当前项目标记为 true。下单后,再次将其他项目的标志切换为真。您可能需要根据标志处理其他一些情况,这种方法会起作用。
    猜你喜欢
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 2021-12-18
    相关资源
    最近更新 更多