📜 ⬆️ ⬇️

Sessions - are they always needed?

I want to once again raise the topic of using sessions to authenticate users. I hope to hear criticism of the method cited in the article from the height of your experience.



Despite all the reasonableness and brilliant implementation of sessions in PHP, most developers sooner or later face the need to extend / change the standard functionality. Here are the main points to be addressed:
  1. Session Fixation. To guard against theft of sessions, the sessid is tied to some information describing
    user This is usually IP or UserAgent, or both.
    ')
    Your session_set_save_handler. Since storing session variables in the file system is far from optimal;
    sooner or later you have to think about transferring sessions to memcached, the base, or wherever.

    session.use_trans_sid = 0. The PHP url_rewriter mechanism built into PHP is an unusually powerful and useful thing, but with
    using it in sessions there is a series of unpleasant moments. "Furious" search engines, ugly links,
    calling under a false name, "lit" your sessid in the logs of completely foreign sites (via HTTP_REFERER), etc.
    Therefore, this function is usually turned off, and only cookies are used to transmit the sessid.


    At the last point, I want to dwell. The fact is that most major sites
    (google, ozon, livejournal, paypal ..) work only through cookies. It seemed to me very strange
    since it is unlikely that people without cookies on the Internet are already so rare that they can be neglected.

    Liveinternet statistics show that the number of people with disconnected cookies is around 4%.
    Not so little. It is unlikely that such giants would deliberately cut off this part of the audience, at least
    there must have been very good reasons. And they were found.

    It turns out that these 4% include those people who do not have regular cookies.
    (with a fixed life), but session sessions work with a lifetime = 0. Session cookies work for almost everyone.
    even those who set “deny cookies” in the security settings, and even in lynx. :)

    It is clear that 100% guarantee still can not be given. For example, a cookie can be cut by a firewall (although again it’s not known
    will he cut with lifetime = 0). A user can have a self-written browser without the support of cookies.
    (for example, crawler on a pearl). But you never know what else ...

    But judging from my own experience, (and the experience of “senior comrades” indirectly confirms this), I would say that in practice
    it is safe to expect that the user has yes session cookies. And also in favor of this thesis says that
    that by default in PHP the session.use_only_cookies parameter is set to 1, i.e. sessions do not work for people without cooks.

    And since we can count on the support of cookies, then in most places where sessions are commonly used, in practice we can make everything easier and more convenient through cookies, and at the same time it will work in all the same cases,
    as the session. Why am I saying simpler? Because the cookie has thrown - and forgot, it is not necessary to register manually when
    header (Location: ..), it is not necessary to remember about it when working with AYAX, it is present in the request, regardless of
    Whether this request refers to a script, static html, image or css. Sessions can only be forgotten if
    if they work through the same cookies, and even then not always. :)

    Now a few words about your own session_set_save_handler. Of course, it all depends on what data and how long we
    need to store. For the general case, of course, you need to use a database or file system. If the lifetime of the session is short,
    and the data itself in the session is easily recoverable, then memory (or memcached) will do quite well. And if the session is used only for
    user authentication, it is worth considering whether it is necessary at all, in principle, to store something on the server side.
    After all, when using cookies, we can completely abandon save_handler, and store all the data with the client.

    Again, a quick look at the cookies left by phpbb, wordpress, gmail, and others showed that such an approach quite often
    used and fully entitled to life. The only thing worth remembering is that cookies can be easily forged,
    so blindly trust them in no case be impossible.

    And here we come to paragraph 1 - Session Fixation. As with the standard session mechanism, its
    Cook we also need to bind to some information that identifies the user to eliminate the possibility of transfer
    her to another. In addition, we must protect the cookie from possible changes by the user.

    As in the case of sessions, this can be done by storing on the server and subsequent reconciliation
    necessary information (same IP and UserAgent).
    But we decided not to store anything on the server. Let's see if this can be done without using server memory.

    Consider the common case of authorization: when you enter the correct username and password, we save the user to the cookie
    its unique identifier (ID), and then every time we access the server we identify the user by this identifier
    and consider logged. If there is no identifier, or the time has expired, we again ask the user for a username and password.

    What are the disadvantages here:
    1. The user can easily change the ID in the cookie, and will be identified by us as another user.

      A user can steal a cookie from another user and impersonate him.

      It is not clear how to determine that time is up. We do not store any timeout on the server, so we don’t know if
      the user has come to us yesterday or he has been coming with the same cookie for two months. We do not remember when he logged in to us
      specifically from this computer.


      In order that the user could not change the data in the cookie, we can use a digital signature. For example, md5
      from some secret word and user id. Or from the password of this user. Or from the password hash, if the password itself is
      We do not store in the database. In short, we need information that the user knows only about himself, but does not know about others.
      users for which he wants to give himself. Or does not know at all (secret word).
      Thus, the cookie we put will look like:
         $ cookie = $ userid.  '|'  .  md5 ($ userid. 'secret word');
      


      In order that the user could not send a cookie to another user, we use IP in the same digital signature and
      UserAgent.
         $ cookie = $ userid.  '|'  .  md5 ($ userid. 'secret word'.   
              $ _SERVER ['REMOTE_ADDR'])
      

      When we receive cookies, we verify the signature using those UserAgent and IP with which this cookie came to us.
      If the signature cookies did not use the values ​​that came now - the signature will not be correct, and we will not accept cookies.

      And finally, the time of action. The easiest thing to do is to score on it: while the user sends us the correct cookie, the correct one
      IP and UserAgent - we start it up. But if we still want to forcefully limit the duration of the session, we can add
      deadline in the cookie itself. And also to sign.

         $ cookie = $ userid.  '|'  .  $ time.  '|'  .  md5 (
      	 $ userid.  $ time.  'secret word'. 
      	 $ _SERVER ['REMOTE_ADDR'].  $ _SERVER ['HTTP_USER_AGENT']
         )
      


      What we have in the end: a completely reliable user authentication mechanism on the site, which creates a minimal load
      to the server.

      What we do not have: we can not store a lot of session data. The size of the cookie is limited, md5 on long lines eats
      CPU time, and it’s useless for the user to download all this garbage back and forth.
      The maximum length is probably worth doing like with gmail - about 120 bytes. Although there can be so much stored in the session
      - I do not know. In any case, if you need to store a lot of variables - then IMHO you should still use the standard
      PHP sessions that are designed for the general case and can be used in ours, albeit with less
      performance.

      We also do not know how many sessions we currently have open. You can open them unlimitedly.
      In principle, nothing prevents us from keeping such records, but we ourselves wanted to unload the server ...

      How is this better than using standard sessions, but with your save_handler and session_fixation? The fact that everything happens in plain sight and you can intervene in any place. The simplicity of the code. Well, the speed - in exchange for versatility.

Source: https://habr.com/ru/post/21918/


All Articles