
PHP Sessions. A detailed description of the work as an explanation of the mechanism.
IntroductionAs arranged, and how they work session?
Scope.
Possible problems and their remedies.
Security
Additional Information:
An example of using sessions authentication
Comments
Introduction
Session - it's actually very simple.
You just need to understand what they need and how to construct.
First to answer the first question.
As shown in the relevant section of this FAQ, the web server does not support a permanent connection to the client, and each request is handled as a new one, without any connection with the previous ones.
That is, we can not track down any requests from the same visitor, nor for him to keep the variables between the scans of individual pages. That is to solve these two problems were invented session.
Actually, the session, in a nutshell - is a mechanism to uniquely identify the browser and creates a file for that browser on the server, which stores session variables.
Details to paint the need for such a mechanism, I will not. These are textbook cases of how the shopping cart in an e-store, authorization, and the same is not quite trivial issues, such as the protection of the interactive parts of the site from spam.
In principle, quite easy to make your own analog sessions, not as functional as the built-in PHP, but similar in nature. In the cookies and the data base.
When prompted for the script look, came a cookie with that name. If cookies are not, then put it into the database and write a new row with user data. If the cookie exists, then read the data from the database. Another query from the database delete old records and now we have prepared the mechanism of the sessions. Is a snap. But there are some nuances that make it preferable to use built-in sessions.
As arranged, and how they work session?
First you need to somehow identify your browser. To do this, give him a unique ID and ask him to pass with every request. I am ashamed to admit it, but when I first learned about the sessions, I thought it was some special mechanism, a new way to communicate with the server browser - "session." What is the session identifier is passed in some special way. The disappointment was cruel.
The sessions use standard, well-known methods of data transmission. Actually, the other-and then just do not.
ID - This is a common variable. By default, its name - PHPSESSID.
Problem PHP to send it to the browser, so that he returned it to the next request. From the FAQ section of the aforementioned it is clear that a variable can only be transferred in two ways: in cookies or POST / GET request.
PHP uses both.
Are responsible for it are two settings in php.ini:
- если равно 1, то PHP передает идентификатор в куках, если 0 - то нет.
session.use_cookies - if equal to 1, PHP will pass the ID in a cookie if 0 - no. если равно 1, то PHP передает его, добавляя к URL и формам, если 0 - то нет.
session.use_trans_sid if equal to 1, PHP will pass it by adding a URL and forms, if 0 - no. или в файлах настройки веб-сервера To change these and other parameters of sessions can be in the same way as other settings PHP - in your php.ini, as well as using the
ini_set() or in the configuration files, the Web server () If only the first, then the start of the session (every time you call
session_start () session_start () ) Set a cookie to the client. The browser correctly every time you request this cookie and PHP returns a session identifier. The problems start when a browser cookie does not return. In this case, not getting the cookie ID, PHP will always start a new session, and the mechanism will not work. If only the second, then the cookie is not placed. And there is something for which, basically, in fact, is to use the built-in sessions. Once the script is doing his job, and the page is fully formed, PHP looks at it all and adds to every link and every form of transmission of session identifiers. It looks like this:
превращается в
<a href="/index.php">Index</a> becomes <a href="/index.php?PHPSESSID=9ebca8bd62c830d3e79272b4f585ff8f">Index</a> and added to the forms of the hidden field
<input type="hidden" name="PHPSESSID" value="00196c1c1a02e4c37ac04f921f4a5eec" /> And the browser when you click on any link or by pressing a button on a form, send in a request variable you want us to - session id!
For obvious reasons, the identifier is added only to the relative links.
Theoretically, is in our homemade cookies and sessions in the database, you can own, hands assigned to all transmission links Eid - and then our own sessions will be run independently of cookies. But you will agree - pleasant, when this work does someone else? ;-)
By default, the latest versions of PHP include both options. As PHP comes in this case? Cook has always exhibited. A reference avtodopolnyayutsya only if PHP did not find a cookie with the session identifier. When the user prvy time for this session comes to your site, he put the cookie, and supplemented by reference. In the following query if cookies are supported, PHP sees the cookie and no longer add links. If cookies are not working, PHP continues to correctly add the id to links, and the session is not lost.
Users who run the cookie will see a long link with ID only once.
Phew. With the transfer of an identifier have finished.
Now we have to tie him to a data file on the server side.
PHP will do it for us. Simply write
session_start ();
$_SESSION [ 'test' ]= 'Hello world!' ; And PHP will write to the file associated with that session, the variable test. It is very important remark.
- особенный. The array
$_SESSION - special. It, in fact, there are variables that we go to make available in a variety of scripts.
To place a variable in the session, you need to assign it to an element of the array $ _SESSION.
To get its value - enough to turn to the same element. An example would be a little lower.
Build waste - disposal of obsolete files, PHP is also involved himself. As well as data encryption and a bunch of all sorts of other useful things. As a result of this care work with the sessions is very simple.
Here we are, in fact, come to the example of the sessions.
The example is very small:
<?
session_start ();
if (!isset( $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ;
echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз. " ;
echo "<br><a href=" . $_SERVER [ 'PHP_SELF' ]. ">обновить" ;
?> $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ; echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз. " ;
echo "<br><a href=" . $_SERVER [ 'PHP_SELF' ]. ">обновить" ;
?> Мы проверяем, есть ли у нас в сессии переменная counter, если нет, то создаем ее со значением 0, а дальше выводим ее значение и увеличиваем на единицу.
<?
session_start ();
if (!isset( $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ;
echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз. " ;
echo "<br><a href=" . $_SERVER [ 'PHP_SELF' ]. ">обновить" ;
?> We check whether we have a session variable counter, if not, create it with the value 0, and then derive its value and increase by one. Increase the value written in the session and the next call to a script variable will be set to 1, and so on. It's very simple.
In order to access the variable session on any web pages, you should write only one (!) Line at the beginning of each file, in which we need session:
session_start (); And then refer to elements of the array $ _SESSION. For example, the authorization check will look like this:
session_start ();
if ( $_SESSION [ 'authorized' ]<> 1 ) {
header ( "Location: /auth.php" );
exit;
} Removing variables from the session.
, то достаточно написать If you have
register_globals=off , it is sufficient to write unset( $_SESSION [ 'var' ]); If not, then next to it to write session_unregister ( 'var' ); Scope.
It is important to understand why the session should be used and for what - no.
First, remember that the session can be applied only when you need them to the user, and not to mend his obstacles. After all, he may at any time to get rid of the ID!
For example, when checking that a person fills out a form and not a script, the user is interested in the session to work - otherwise it would not be able to send the form! But to limit the number of requests to the script session is not good - a malicious script simply will not return the ID.
Second. It is important to clearly imagine the fact that the session - a session with the site, because it understands people. He came, worked, closed the browser - the session is over. As the session to the movies. Want to see another one - buy a new ticket. Start a new conversation. There is some technical explanation. Guaranteed session mechanism works only is to close your browser. After all, the client may not work the cookies, but in this case, of course, all complemented by an identifier links disappear with its closure.
However, the session may be lost, and without closing the browser. In view of the restrictions discussed in the main section of this FAQ, mechanism of sessions can not detect when the user closed the browser. It uses a timeout - a predetermined time after which, we believe that the user left the site. The default setting is 24 minutes.
If you want to store user information for a longer period, then use a cookie and, if necessary - a database on the server. In particular, this is how all the popular operating system authentication:
- In fact identify a user session begins, and a sign avtorizovannosti passed to it.
- If you need to "remember" the user, then he put the cookie, it identifies.
- The next time the user enters the site to log in, he must either enter a password, or the system will recognize it by the previously set cookie and starts the session. A new session rather than continuing the old.
Thirdly, we should not start session without discrimination, each input to the site. This will create an entirely unnecessary burden. Do not use the session for nothing - for example, in meters. That calls spaylog sessions is, of course, on the basis of statistical approaches, rather than through the mechanism of the sessions, similar to php-shnomu.
Also, take a search engine that indexes your site. If the crawler does not support cookies, then the default php will provide links to the PHPSESSID, that - soglasistes - maybe not much like the search engine, which is rumored to be dynamic and such links does not favor, but here at all for each entry - new address !
If the session is used to restrict access to the private area of this site is all just a search engine and it should not be indexed.
If it is necessary to show the same page as the authorized and non authorized users, then there will a trick - start a session only to those who entered the password, or those who have already started session.
() To do this, the top of each page instead of just
session_start () session_start () write if (isset( $_REQUEST [ session_name ()])) session_start (); Thus, we start the session only to those who sent the identifier. Accordingly, we must have for the first time to send it to the user - at the time of authorization.
() If the name is correct and shed - write
session_start () session_start () ! Possible problems and their remedies.
The most common errors that PHP gives when you try to work with the sessions are as follows:
Two of them,
Warning: Cannot send session cookie - headers already sent
Warning: Cannot send session cache limiter - headers already sent caused by the same reason, the solution described in this Fake is
The third,
(ранее она выглядела, как
Warning: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/tmp) ), Warning: open(/tmp\sess_SID, O_RDWR) failed: No such file or directory (2) in full_script_path on line number (before it looked like Warning: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/tmp) ), if you translate it to English, explains in detail the problem: not available specified in php.ini path to the directory where the files are written in the sessions. This error is the easiest to fix. Just to put the directory that exists and is writable, for example,
session.save_path = c:\windows\temp And do not forget to restart apache after this.
As it turns out, The Human ingenuity has no limits, so I had to explain:
third error message (can not find a directory) will inevitably lead to the emergence of the first two, because the error message - it is output to the browser and after the headers can not be used. So do not rush to seek a premature conclusion, but first list the right way!
The next most common problem when dealing with the painful legacy of the sessions is register_globals. Do not let the script variable names that match the index of the array $ _SESSION!
When register_globals = on values will overwrite each other, and you get stuck.
And with register_globals = off another error appears: "Your script possibly relies on a session side-effect which existed until PHP 4.2.3.", If there is a variable in a script session, which has no value, and the global variable with the same name . To get rid of it, we must always initialize variables before you use (or at least check for existence) and not give the names of global variables, which coincide with the indices of the array $ _SESSION.
When not working, but no message is displayed, then add in the very beginning of the script two lines are responsible for the withdrawal of all errors on the screen - it is possible that the error is, but you just do not see them.
ini_set ( 'display_errors' , 1 );
error_reporting ( E_ALL ); or see the error in the error_log. In general, the theme display error messages is beyond the scope of this article, so just make sure at least that you can see them. Just prodrobnee about finding bugs can be found in this section . If you believe that there are no errors, but this example does not work anyway, it's possible in PHP does not include the transfer of the id by url, and cookies for some reason do not work.
See what you have with cookies.
Generally, if you "do not work" session, you must first try to pass the session identifier hands, that is, to make the link, and assign it an identifier:
<?
session_start ();
if (!isset( $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ;
echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз.<br>
<a href=" . $_SERVER [ 'PHP_SELF' ]. '?' . session_name (). '=' . session_id (). ">обновить</a>" ;
?> $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ; echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз.<br>
<a href=" . $_SERVER [ 'PHP_SELF' ]. '?' . session_name (). '=' . session_id (). ">обновить</a>" ;
?> При этом следует убедиться, что не включена директива
session.use_only_cookies , которая запрещает PHP принимать идентификатор сессии, если он был передан через URL <?
session_start ();
if (!isset( $_SESSION [ 'counter' ])) $_SESSION [ 'counter' ]= 0 ;
echo "Вы обновили эту страницу " . $_SESSION [ 'counter' ]++. " раз.<br>
<a href=" . $_SERVER [ 'PHP_SELF' ]. '?' . session_name (). '=' . session_id (). ">обновить</a>" ;
?> This should ensure that the directive is not included session.use_only_cookies , which prohibits the taking PHP session id, if it was passed through the URL - в 4.1 (До этого использовался
$HTTP_SESSION_VARS ). If this example does not work, then the problem is either banal typos (half of the "problems" with the sessions comes from the misspelled variable name) or too old versions of PHP: Support sessions appeared in version 4.0, and the array $_SESSION - in 4.1 (Up to We used the $HTTP_SESSION_VARS ). If the work - the problem is in the cookie. Track - a cookie that puts the server browser if the browser returns it. Search is very useful, looking at looking at HTTP-headers exchanged between browser and server.
An explanation of the principle of cookies goes beyond this and so too much text, but at least make sure that the server sends a cookie with the ID and the browser - returns. And at the same identifiers coincide with each other =)
Set the cookie should look like
или как
Set-Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6; or as (если вы запрашиваете скрипт не из корневого каталога)
Set-Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6; path=/ (unless you request script is not in the root directory) The server response should look like
либо
Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6 or если браузер возвращает другие куки, кроме идентификатора сессии.
Cookie: PHPSESSID=prlgdfbvlg5fbsbshch6hj0cq6; b=b if the browser returns the cookie other than the session ID. If your browser cookies will not return - check whether the cookie at all.
Make sure the domain to which you refer, has a normal name (which has at least one point and does not contain illegal characters such as underscores) and clean your browser cache - are two main reasons for Kotormo cookies may not work.
If the example from this work, and your own code - no, the problem is obviously not in the sessions, and in the algorithm. Look where the lost variable in steps.
Another problem can occur if you use a redirect header or navigation using JavaScript.
, но не делает этого для header-ов, яваскрипта, мета-тегов. The fact that PHP automatically appends the session id only to listed species
<a href=> , but it does not do this for the header-s, javascript, meta tags. Therefore it is necessary to add the ID with his hands, like this:
header ( "Location: /script.php?" . session_name (). '=' . session_id ()); It should be remembered that the php file lochit session. That is, if your script starts a session and long runs, and the other at this time trying to start it with the same identifier, it will hang. Therefore, in the long-running scripts should start a session only when it is needed, and then close it, using
session_write_close() It is also very rare, and it is unclear from appearing, the problem is that setting session.save_handler has a value other than files. If it is not - fix.
Security
Safety sessions - a vast topic. Therefore, focus on several key points.
Most textbook - not to pass the ID via the URL. For it is written, even in php.ini, but this limits the functionality of the sessions. If you decide to follow this advice, except session.use_trans_sid = 0 do not forget to session.use_only_cookies = 1
It is advisable to tie the session to the IP address: thus, if the ID is stolen, the villain would not be able to use it in most cases.
It is recommended to use the directive session.save_path, with which to specify your own directory to store session files. It is more secure than when they are stored in the temporary directory general of the default server.
Additional Information:
session_cache_limiter ( "private" ); before the start of the session to resolve the issue. $_SESSION [ 1 ], $_SESSION [ '10' ] As it may seem strange, but in the array $_SESSION can not use numeric codes - $_SESSION [ 1 ], $_SESSION [ '10' ] $_SESSION [ 1 ], $_SESSION [ '10' ] - Sessions related will not work. ini_set () Somewhere between versions 4.2 and 5.0 it was impossible to session.use_trans_sid using ini_set () ini_set () . Starting with 5.0 you can have again. session_start () session_start () An example of using sessions authentication
We illustrate all vyshenapisannogo small example:
create file auth.php:
<?
if (isset( $_POST [ 'auth_name' ])) {
$name = mysql_real_escape_string ( $_POST [ 'auth_name' ]);
$pass = mysql_real_escape_string ( $_POST [ 'auth_pass' ]);
$query = "SELECT * FROM users WHERE name='$name' AND pass='$pass'" ;
$res = mysql_query ( $query ) or trigger_error ( mysql_error (). $query );
if ( $row = mysql_fetch_assoc ( $res )) {
session_start ();
$_SESSION [ 'user_id' ] = $row [ 'id' ];
$_SESSION [ 'ip' ] = $_SERVER [ 'REMOTE_ADDR' ];
}
header ( "Location: http://" . $_SERVER [ 'HTTP_HOST' ]. $_SERVER [ 'REQUEST_URI' ]);
exit;
}
if (isset( $_GET [ 'action' ]) AND $_GET [ 'action' ]== "logout" ) {
session_start ();
session_destroy ();
header ( "Location: http://" . $_SERVER [ 'HTTP_HOST' ]. "/" );
exit;
}
if (isset( $_REQUEST [ session_name ()])) session_start ();
if (isset( $_SESSION [ 'user_id' ]) AND $_SESSION [ 'ip' ] == $_SERVER [ 'REMOTE_ADDR' ]) return;
else {
?>
<form method="POST">
<input type="text" name="auth_name"><br>
<input type="password" name="auth_pass"><br>
<input type="submit"><br>
</form>
<?
}
exit;
?> Now it suffices to write scripts in all the protected line
require "auth.php";
Just out of date, unfortunately, and many other articles, which lie on the internet and have not been updated for years.
by phpfaq.ru
