Home  >  Article  >  Backend Development  >  Analyze related operations of cookie and session functions in PHP's Yii framework_php skills

Analyze related operations of cookie and session functions in PHP's Yii framework_php skills

WBOY
WBOYOriginal
2016-05-16 19:56:361058browse

Sessions

Similar to requests and responses, sessions can be accessed by default through the session application component of the yiiwebSession instance.

Open and close Sessions

You can use the following code to open and close the session.

$session = Yii::$app->session;

// 检查session是否开启 
if ($session->isActive) ...

// 开启session
$session->open();

// 关闭session
$session->close();

// 销毁session中所有已注册的数据
$session->destroy();

Calling the yiiwebSession::open() and yiiwebSession::close() methods multiple times will not cause an error, because the method will first check whether the session is open.

Access Session Data

To access the data stored in session, you can do the following:

$session = Yii::$app->session;

// 获取session中的变量值,以下用法是相同的:
$language = $session->get('language');
$language = $session['language'];
$language = isset($_SESSION['language']) ? $_SESSION['language'] : null;

// 设置一个session变量,以下用法是相同的:
$session->set('language', 'en-US');
$session['language'] = 'en-US';
$_SESSION['language'] = 'en-US';

// 删除一个session变量,以下用法是相同的:
$session->remove('language');
unset($session['language']);
unset($_SESSION['language']);

// 检查session变量是否已存在,以下用法是相同的:
if ($session->has('language')) ...
if (isset($session['language'])) ...
if (isset($_SESSION['language'])) ...

// 遍历所有session变量,以下用法是相同的:
foreach ($session as $name => $value) ...
foreach ($_SESSION as $name => $value) ...

Supplement: When using the session component to access session data, if the session is not opened, it will be opened automatically. This is different from $_SESSION, which requires session_start() to be executed first.

When the session data is an array, the session component will restrict you from directly modifying the unit items in the data, for example:

$session = Yii::$app->session;

// 如下代码不会生效
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;

// 如下代码会生效:
$session['captcha'] = [
  'number' => 5,
  'lifetime' => 3600,
];

// 如下代码也会生效:
echo $session['captcha']['lifetime'];

Use any of the following workarounds to resolve this issue:

$session = Yii::$app->session;

// 直接使用$_SESSION (确保Yii::$app->session->open() 已经调用)
$_SESSION['captcha']['number'] = 5;
$_SESSION['captcha']['lifetime'] = 3600;

// 先获取session数据到一个数组,修改数组的值,然后保存数组到session中
$captcha = $session['captcha'];
$captcha['number'] = 5;
$captcha['lifetime'] = 3600;
$session['captcha'] = $captcha;

// 使用ArrayObject 数组对象代替数组
$session['captcha'] = new \ArrayObject;
...
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;

// 使用带通用前缀的键来存储数组
$session['captcha.number'] = 5;
$session['captcha.lifetime'] = 3600;

For better performance and readability, the last solution is recommended, which is not to store session variables as arrays, but to turn each array item into a session variable with the same key prefix.

Customized Session Storage

The yiiwebSession class stores session data as files on the server by default. Yii provides the following session classes to implement different session storage methods:

    yiiwebDbSession: Store session data in the data table
  • yiiwebCacheSession: Stores session data in the cache. The cache is related to the cache component in the configuration
  • yiiredisSession: Store session data in redis as the storage medium
  • yiimongodbSession: Store session data in MongoDB.
All these session classes support the same set of API methods, so switching to a different session storage medium does not require modifying the project's code that uses the session.

Note: If you access a session using a custom storage medium through $_SESSION, you need to ensure that the session has been opened using yiiwebSession::open(). This is because the custom session storage processor is registered in this method.

To learn how to configure and use these component classes, please refer to their API documentation. The following is an example showing how to configure yiiwebDbSession in the application configuration to use the data table as the session storage medium.

return [
  'components' => [
    'session' => [
      'class' => 'yii\web\DbSession',
      // 'db' => 'mydb', // 数据库连接的应用组件ID,默认为'db'.
      // 'sessionTable' => 'my_session', // session 数据表名,默认为'session'.
    ],
  ],
];
You also need to create the following database table to store session data:

CREATE TABLE session
(
  id CHAR(40) NOT NULL PRIMARY KEY,
  expire INTEGER,
  data BLOB
)
Where 'BLOB' corresponds to the BLOB-type of the database management system you choose. The following are the BLOB types of some commonly used database management systems:

    MySQL: LONGBLOB
  • PostgreSQL: BYTEA
  • MSSQL: BLOB
Note: According to the session.hash_function set in php.ini, you need to adjust the length of the id column. For example, if session.hash_function=sha256, a char type with a length of 64 instead of 40 should be used.

Flash data

Flash data is a special kind of session data. Once it is set in a request, it will only be valid in the next request, and then the data will be automatically deleted. It is often used to implement information that only needs to be displayed to the end user once, such as displaying confirmation information after the user submits a form.

Session can be set or accessed through the session application component, for example:

$session = Yii::$app->session;

// 请求 #1
// 设置一个名为"postDeleted" flash 信息
$session->setFlash('postDeleted', 'You have successfully deleted your post.');

// 请求 #2
// 显示名为"postDeleted" flash 信息
echo $session->getFlash('postDeleted');

// 请求 #3
// $result 为 false,因为flash信息已被自动删除
$result = $session->hasFlash('postDeleted');

Similar to ordinary session data, any data can be stored as flash data.

When calling yiiwebSession::setFlash(), any existing data with the same name will be automatically overwritten. To append data to the existing flash with the same name, you can call yiiwebSession::addFlash() instead. For example:

$session = Yii::$app->session;

// 请求 #1
// 在名称为"alerts"的flash信息增加数据
$session->addFlash('alerts', 'You have successfully deleted your post.');
$session->addFlash('alerts', 'You have successfully added a new friend.');
$session->addFlash('alerts', 'You are promoted.');

// 请求 #2
// $alerts 为名为'alerts'的flash信息,为数组格式
$alerts = $session->getFlash('alerts');

Note: Do not use yiiwebSession::setFlash() and yiiwebSession::addFlash() on flash data with the same name, because the latter precaution will automatically convert the flash information into an array to make the new flash data available appended in. Therefore, when you call yiiwebSession::getFlash(), you will find that sometimes you get an array and sometimes you get a string, depending on the order in which you call these two methods.


Cookies

Yii uses the yiiwebCookie object to represent each cookie. yiiwebRequest and yiiwebResponse maintain a cookie collection through an attribute named 'cookies'. The former's cookie collection represents the cookies submitted by the request, and the latter's cookie collection represents the cookies sent to the user. .

Read Cookies

The currently requested cookie information can be obtained through the following code:

// 从 "request"组件中获取cookie集合(yii\web\CookieCollection)
$cookies = Yii::$app->request->cookies;

// 获取名为 "language" cookie 的值,如果不存在,返回默认值"en"
$language = $cookies->getValue('language', 'en');

// 另一种方式获取名为 "language" cookie 的值
if (($cookie = $cookies->get('language')) !== null) {
  $language = $cookie->value;
}

// 可将 $cookies当作数组使用
if (isset($cookies['language'])) {
  $language = $cookies['language']->value;
}

// 判断是否存在名为"language" 的 cookie
if ($cookies->has('language')) ...
if (isset($cookies['language'])) ...

Send Cookies

You can send cookies to end users using the following code: You can use the following code to send cookies to end users:

// 从"response"组件中获取cookie 集合(yii\web\CookieCollection)
$cookies = Yii::$app->response->cookies;

// 在要发送的响应中添加一个新的cookie
$cookies->add(new \yii\web\Cookie([
  'name' => 'language',
  'value' => 'zh-CN',
]));

// 删除一个cookie
$cookies->remove('language');
// 等同于以下删除代码
unset($cookies['language']);

除了上述例子定义的 yii\web\Cookie::name 和 yii\web\Cookie::value 属性 yii\web\Cookie 类也定义了其他属性来实现cookie的各种信息,如 yii\web\Cookie::domain, yii\web\Cookie::expire 可配置这些属性到cookie中并添加到响应的cookie集合中。

注意: 为安全起见yii\web\Cookie::httpOnly 被设置为true,这可减少客户端脚本访问受保护cookie(如果浏览器支持)的风险, 更多详情可阅读 httpOnly wiki article for more details.
Cookie验证

在上两节中,当通过request 和 response 组件读取和发送cookie时,你会喜欢扩展的cookie验证的保障安全功能,它能 使cookie不被客户端修改。该功能通过给每个cookie签发一个哈希字符串来告知服务端cookie是否在客户端被修改, 如果被修改,通过request组件的yii\web\Request::cookiescookie集合访问不到该cookie。

注意: Cookie验证只保护cookie值被修改,如果一个cookie验证失败,仍然可以通过$_COOKIE来访问该cookie, 因为这是第三方库对未通过cookie验证自定义的操作方式。
Cookie验证默认启用,可以设置yii\web\Request::enableCookieValidation属性为false来禁用它,尽管如此,我们强烈建议启用它。

注意: 直接通过$_COOKIE 和 setcookie() 读取和发送的Cookie不会被验证。
当使用cookie验证,必须指定yii\web\Request::cookieValidationKey,它是用来生成s上述的哈希值, 可通过在应用配置中配置request 组件。

return [
  'components' => [
    'request' => [
      'cookieValidationKey' => 'fill in a secret key here',
    ],
  ],
];

补充: yii\web\Request::cookieValidationKey 对你的应用安全很重要, 应只被你信任的人知晓,请不要将它放入版本控制中。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn