jquery自定义会话_编写自定义会话处理程序

jquery自定义会话

Session are a tool which helps the web programmer overcome the stateless nature of the internet. You can use them to build shopping carts, monitor visits to a website, and even track how a user navigates through your application. PHP’s default session handling behavior can provide all you need in most cases, but there may be times when you want to expand the functionality and store session data differently. This article will show you how the default functionality works and then goes on to show you how override it to provide a custom solution.

会话是一种工具,可以帮助Web程序员克服Internet的无状态本质。 您可以使用它们来构建购物车,监视对网站的访问,甚至跟踪用户如何浏览您的应用程序。 PHP的默认会话处理行为可以在大多数情况下满足您的所有需求,但是有时您可能需要扩展功能并以不同的方式存储会话数据。 本文将向您展示默认功能的工作原理,然后继续向您展示如何重写默认功能以提供自定义解决方案。

会话存储的剖析 (The Anatomy of Session Storage)

Before you implement a custom session save handler, it’s helpful to understand how PHP stores session data normally. The data is saved in a small file on the server which is associated with a unique ID which is then stored in a cookie on the client by the browser. If cookies aren’t used, the ID is usually passed along as a parameter in the URL. Whichever method is used, PHP retrieves the session data in subsequent page requests using the session ID. You can examine how this works by first determining where PHP saves the session data and examine its contents. You can check the session.save_path directive in your php.ini file, or use the session_save_path() function to output the path.

在实现自定义会话保存处理程序之前,了解PHP如何正常存储会话数据会很有帮助。 数据保存在服务器上的一个小文件中,该文件与唯一的ID相关联,然后由浏览器存储在客户端的Cookie中。 如果不使用cookie,则通常会将ID作为参数传递给URL。 无论使用哪种方法,PHP都使用会话ID在随后的页面请求中检索会话数据。 您可以通过首先确定PHP将会话数据保存在何处并检查其内容来检查其工作方式。 您可以在php.ini文件中检查session.save_path指令,或使用session_save_path()函数输出路径。

<?php
echo session_save_path();

The output will be the path to where the session data is stored. You can change the location in php.ini or by simply passing the new path to the session_save_path() function.

输出将是存储会话数据的路径。 您可以在php.ini更改位置,也可以将新路径简单地传递给session_save_path()函数。

<?php
session_save_path("/path/to/session/data");

If you want to set a different directory in which to store session data, it’s a good practice to pick a location that’s outside your root web directory as this can reduce the risk of someone hijacking a session. Just make sure you’ve given the directory adequate permissions to be read from and written to by the server.

如果要设置用于存储会话数据的其他目录,则最好选择一个根Web目录之外的位置,因为这样可以减少有人劫持会话的风险。 只要确保您已授予目录足够的权限即可从服务器读取和写入服务器。

Now that you know where the session data is stored, you can navigate to that directory and find the individual files that store the information related to each active session. Typically the name of the files is “sess_” followed by the session ID associated with the data. You can find out what your session ID is by using the session_id() function.

现在您知道会话数据的存储位置,您可以导航到该目录并找到存储与每个活动会话相关的信息的单个文件。 通常,文件名是“ sess_”,后跟与数据关联的会话ID。 您可以使用session_id()函数找出您的会话ID。

<?php
echo session_id();

The output is a pseudo-random string of 32 characters, much like the following:

输出是32个字符的伪随机字符串,非常类似于以下内容:

k623qubavm8acku19somu6ce1k0nb9aj

Opening the file sess_k623qubavm8acku19somu6ce1k0nb9aj you’ll see a string which describes the data in the session. If you were to store the following array in the session like this:

打开文件sess_k623qubavm8acku19somu6ce1k0nb9aj您将看到一个描述会话中数据的字符串。 如果要像这样在会话中存储以下数组:

<?php
$arr = array("red", "blue"); 
$_SESSION["colors"] = $arr;

The contents of the file would look like this:

该文件的内容如下所示:

colors|a:2:{i:0;s:3:"red";i:1;s:4:"blue";}

The data is encoded in much the same way the serialize() function would treat the data. When data is stored in a session, all of it is collated together, serialized and, in the case of the default session storage mechanism in PHP, placed in a file. When you need to retrieve the data, the session unserializes the data for use by the application.

数据的编码方式与serialize()函数对待数据的方式几乎相同。 当数据存储在会话中时,所有数据将整理在一起,进行序列化,如果使用PHP中的默认会话存储机制,则将其放置在文件中。 当您需要检索数据时,会话会反序列化数据以供应用程序使用。

The thing to remember here is that the default way in which sessions read and write data is via the serialize() and unserialize() functions. The same will hold true if you were to alter the way in which this data was stored. You can change where the data is stored but not how it is stored.

这里要记住的是,会话读取和写入数据的默认方式是通过serialize()unserialize()函数。 如果您要更改此数据的存储方式,则同样适用。 您可以更改数据的存储位置,但不能更改其存储方式。

会话生命周期 (The Session Life Cycle)

When you start or continue a session with session_start(), the session’s data file is opened and the data is read into the $_SESSION array. When the script’s execution ends, the data is saved back to the file. So when you set a session variable, it is not immediately stored. You can, of course, force the session to store the data by calling session_write_close().

当您使用session_start()启动或继续会话时,将打开该会话的数据文件,并将数据读入$_SESSION数组。 当脚本的执行结束时,数据将保存回文件中。 因此,当您设置会话变量时,不会立即存储它。 当然,您可以通过调用session_write_close()来强制会话存储数据。

session_set_save_handler() provides a way to override the default session handling mechanism with new functionality so that you can store the data where you’d like. It requires six arguments, each a callback that handles a specific stage of the session life cycle. They are:

session_set_save_handler()提供了一种使用新功能覆盖默认会话处理机制的方法,以便您可以将数据存储在所需的位置。 它需要六个自变量,每个自变量用于处理会话生命周期的特定阶段。 他们是:

  1. Opening the session file

    打开会话文件
  2. Closing the session file

    关闭会话文件
  3. Reading the session data

    读取会话数据
  4. Writing the session data

    写入会话数据
  5. Destroying the session

    破坏会议
  6. Garbage collection of the session file and data

    垃圾收集会话文件和数据

You must register a function for each stage of the life cycle or PHP will emit a warning that it cannot locate the function.

您必须在生命周期的每个阶段都注册一个函数,否则PHP将发出警告,指出无法找到该函数。

Warning: session_set_save_handler(): Argument 1 is not a valid callback

The callbacks can be defined in any way that PHP allows, so they could be straight functions, closures, object methods, or static class methods.

回调可以用PHP允许的任何方式定义,因此它们可以是直接函数,闭包,对象方法或静态类方法。

<?php
session_set_save_handler("open", "close", "read", "write", "destroy", "garbage");

In this example I’ve assumed the functions open(), close(), read(), write(), destroy(), and garbage() have been defined and registered them as callbacks to session_set_save_handler().

在此示例中,我假设已定义函数open()close()read()write()destroy()garbage()并将它们注册为session_set_save_handler()回调。

创建自定义会话保存处理程序 (Creating a Custom Session Save Handler)

To showcase each callback function I will override the default session handling behavior to instead store them within a MySQL database. The basic schema for the table should include a field for the session ID, a field for the data and a field to determine the time the session was last accessed.

为了展示每个回调函数,我将覆盖默认的会话处理行为,以将其存储在MySQL数据库中。 该表的基本架构应包括用于会话ID的字段,用于数据的字段和用于确定会话上次访问时间的字段。

CREATE TABLE session ( 
    session_id CHAR(32) NOT NULL, 
    session_data TEXT NOT NULL, 
    session_lastaccesstime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (session_id)
);

The default method of generating a session ID uses the MD5 algorithm which generates a 32-character string, and so I’ve set my session_id field as CHAR(32). The data held by the session can be unlimited but it’s good practice not to abuse this facility. The access time field can be of type TIMESTAMP.

生成会话ID的默认方法使用MD5算法,该算法生成一个32个字符的字符串,因此我将session_id字段设置为CHAR(32) 。 会话保存的数据可以是无限的,但是最好不要滥用此功能。 访问时间字段可以是TIMESTAMP类型。

开始会议 (Opening the Session)

The first stage the session goes through is the opening of the session file. Here you can perform any action you like; the PHP documentation indicates that this function should be treated as a constructor, so you could use it to initialize class variables if you’re using an OOP approach. The callback takes two arguments which are passed automatically – the save path and the name of the session.

会话的第一步是打开会话文件。 您可以在此处执行自己喜欢的任何操作; PHP文档指出此函数应视为构造函数,因此,如果您使用的是OOP方法,则可以使用它来初始化类变量。 回调采用两个自动传递的参数-保存路径和会话名称。

<?php
function open($path, $name) {
    $db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");

    $sql = "INSERT INTO session SET session_id =" . $db->quote($sessionId) . ", session_data = '' ON DUPLICATE KEY UPDATE session_lastaccesstime = NOW()";
    $db->query($sql);    
}

The example implementation here will create an entry in the database to stores the data. In the event session entry already exists, the session_last_accesstime will be updated with the current timestamp. The timestamp is used to ensure the session is “live”; it is used later with garbage collection to purge stale sessions which I will discuss shortly.

这里的示例实现将在数据库中创建一个条目来存储数据。 如果会话条目已存在,则将使用当前时间戳更新session_last_accesstime 。 时间戳用于确保会话处于“实时”状态; 稍后将其与垃圾回收一起用于清除过时的会话,我将在稍后讨论。

阅读会议 (Reading the Session)

Immediately after the session is opened, the contents of the session are read from whatever store you have nominated and placed into the $_SESSION array. The callback takes one argument which is the session ID which enables you to identify the session that is being read. The callback must return a string of serialized data as PHP will then unserialize it as discussed previously. There is no need to cater for this in your code. If there is no session data for this session, you should return an empty string.

会话打开后,立即从您指定的任何存储中读取会话的内容,并将其放入$_SESSION数组。 回调采用一个参数,它是会话ID,使您可以识别正在读取的会话。 回调必须返回一个序列化数据的字符串,因为PHP将会如前所述对它进行反序列化。 您的代码中无需满足此要求。 如果此会话没有会话数据,则应返回一个空字符串。

<?php
function read($sessionId) { 
    $db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");

    $sql = "SELECT session_data FROM session where session_id =" . $db->quote($sessionId);
    $result = $db->query($sql);
    $data = $result->fetchColumn();
    $result->closeCursor();

    return $data;
}

It is important to understand that this data is not pulled every time you access a session variable. It is only pulled at the beginning of the session life cycle when PHP calls the open callback and then the read callback.

重要的是要了解,每次访问会话变量时都不会提取此数据。 仅当PHP调用open回调然后读取read回调时,才在会话生命周期的开始将其拉出。

写会议 (Writing to the Session)

Writing the data back to whatever store you’re using occurs either at the end of the script’s execution or when you call session_write_close(). The callback receives two arguments, the data that is to be written and the session ID. The data received will already have been serialized by PHP.

将数据写回到您正在使用的任何存储中,要么发生在脚本执行的最后,要么发生在您调用session_write_close() 。 回调接收两个参数,即要写入的数据和会话ID。 接收到的数据已经由PHP进行了序列化。

<?php
function write($sessionId, $data) { 
    $db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");

    $sql = "INSERT INTO session SET session_id =" . $db->quote($sessionId) . ", session_data =" . $db->quote($data) . " ON DUPLICATE KEY UPDATE session_data =" . $db->quote($data);
    $db->query($sql)
}

There are numerous ways in which you can handle the data that is passed into the read and write callbacks. PHP passes the data in serialized to the write function, and expects it serialized back from the read function, but that doesn’t mean you have to store it that way. You could unserialize the data immediately in the write callback and then perform some action dependent on the data or store it however you wish. The same applies to the read callback. All these decisions are implementation dependent and it’s up to you to decide what’s best for your situation.

您可以通过多种方式来处理传递到读写回调中的数据。 PHP将数据以序列化方式传递给write函数,并期望将其从read函数中序列化为序列,但这并不意味着您必须以这种方式进行存储。 您可以立即在写回调中反序列化数据,然后根据数据执行某些操作或将其存储为所需的格式。 读取回调也是如此。 所有这些决定都取决于实现方式,由您决定哪种方式最适合您的情况。

会议闭幕 (Closing the Session)

Closing the session occurs at the end of the session life cycle, just after the session data has been written. No parameters are passed to this callback so if you need to process something here specific to the session, you can call session_id() to obtain the ID.

在会话生命周期结束时,即在写入会话数据之后,才关闭会话。 没有参数传递给此回调,因此,如果您需要在此处处理特定于会话的某些内容,则可以调用session_id()获取ID。

<?php
function close() {
    $sessionId = session_id();
    //perform some action here
}

破坏会议 (Destroying the Session)

Destroying the session manually is essential especially when using sessions as a way to secure sections of your application. The callback is called when the session_destroy() function is called. The session ID is passed as a parameter.

手动销毁会话至关重要,尤其是在使用会话作为保护应用程序部分安全的方式时。 调用session_destroy()函数时,将调用该回调。 会话ID作为参数传递。

<?php
function destroy($sessionId) {
    $db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");

    $sql = "DELETE FROM session WHERE session_id =" . $db->quote($sessionId); 
    $db->query($sql);

    setcookie(session_name(), "", time() - 3600);
}

In its default session handling capability, the session_destroy() function will clear the $_SESSION array of all data. The documentation on php.net states that any global variables or cookies (if they are used) will not cleared, so if you are using a custom session handler you can perform these tasks in this callback also.

在其默认会话处理功能中, session_destroy()函数将清除$_SESSION数组的所有数据。 php.net上的文档指出,不会清除任何全局变量或cookie(如果使用了它们),因此,如果您使用的是自定义会话处理程序,则也可以在此回调中执行这些任务。

垃圾收集 (Garbage Collection)

The session handler needs to cater to the fact that the programmer won’t always have a chance to manually destroy session data. For example, you may destroy session data when a user logs out and it is no longer needed, but there’s no guarantee a user will use the logout functionality to trigger the deletion. The garbage collection callback will occasionally be invoked by PHP to clean out stale session data. The parameter that is passed here is the max lifetime of the session which is an integer detailing the number of seconds that the lifetime spans.

会话处理程序需要满足这样一个事实,即程序员不会总是有机会手动销毁会话数据。 例如,您可以在用户注销并且不再需要会话数据时销毁会话数据,但不能保证用户将使用注销功能来触发删除。 PHP有时会调用垃圾回收回调来清除陈旧的会话数据。 此处传递的参数是会话的最大生存期,它是一个整数,详细说明了生存期的秒数。

<?php
function gc($lifetime) {
    $db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");

    $sql = "DELETE FROM session WHERE session_lastaccesstime < DATE_SUB(NOW(), INTERVAL " . $lifetime . " SECOND)";
    $db->query($sql);
}

Garbage collection is performed on a random basis by PHP. The probability that garbage collection is invoked is decided through the php.ini directives session.gc_probability and session.gc_divisor. If the probability is set to 1 and the divisor is set to 100 for example, the garbage collector has a 1% chance of being run on each request (1/100).

垃圾收集是由PHP随机执行的。 垃圾回收被调用的可能性由php.ini指令session.gc_probabilitysession.gc_divisor决定。 例如,如果将概率设置为1,将除数设置为100,则垃圾回收器将对每个请求运行的概率为1%(1/100)。

The example callback uses the max lifetime of the session to compare the time that the session was last accessed. If the lifetime of the session has been exceeded, it removes the session and all data relating to it.

示例回调使用会话的最长生存期来比较上次访问会话的时间。 如果已超过会话的生存期,它将删除该会话及其所有相关数据。

摘要 (Summary)

Changing the default behavior of PHP’s session handling can be useful in numerous situations. This article showed you how PHP treats session data “out of the box” and how this can be changed to suit your own application’s needs by storing the data in a MySQL database. Of course, you could pick your favorite database or another solution such as XML, Memcache, or another file-based system. Unserializing the data before it’s written will enable you to store the data as you see fit, just remember that you have to send the data back in serialized form in order for PHP to make use of it when it’s read.

在许多情况下,更改PHP会话处理的默认行为可能很有用。 本文向您展示了PHP如何“开箱即用”处理会话数据,以及如何通过将数据存储在MySQL数据库中进行更改以满足您自己的应用程序的需求。 当然,您可以选择自己喜欢的数据库或其他解决方案,例如XML,Memcache或其他基于文件的系统。 在写入数据之前对数据进行反序列化将使您能够按自己的意愿存储数据,只需记住,必须以串行化的形式将数据发送回去,以便PHP在读取数据时可以使用它。

Image via Sergey Mironov / Shutterstock

图片来自Sergey Mironov / Shutterstock

翻译自: https://www.sitepoint.com/writing-custom-session-handlers/

jquery自定义会话

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值