Dear all,

I recently implemented an user authentication mechanism on a web site for only allowing members to view the secure contents. The authentication mechanism itself works great.

However I found a problem in it. When I log out from the secure contents (a button for logging out is placed there), if I hit the Back Button, the browser (IE6) asks me if I want to resend the cached info and if I hit yes, the browser resends the Form data, in this case, the "previously input User ID and Password", and I am logged in again and the secure contents are showing again!

I don't want this to happen. Suppose I just logged out from the secure contents session, the browser returned to the log in screen. I left the computer and another user came and hit the Back button and he would see all my secure contents!

The codes are as follows:

<?php

  [COLOR=DarkOrange]// start session if not already started[/COLOR]

  session_start();


  [COLOR=DarkOrange]// check to see if user just logged out by hitting the logout button[/COLOR]

  $logout = $_POST['FormLogout'];   [COLOR=DarkOrange]// a hidden Form field with value of 1 returned by the logout button[/COLOR]

  if ($logout) {

session_unregister("valid_user");

session_unset();

session_destroy();

session_start();

  }


  function write_login($mesg) {

echo $mesg;

echo "  <FORM name=\"FormLogin\" action=\"\" method=\"post\">";

echo "    User ID:";

echo "    <INPUT type=\"text\" name=\"FormUser\">";

echo "    Password:";

echo "    <INPUT type=\"password\" name=\"FormPassword\">";

echo "    <INPUT type=\"submit\" value=\"Login\">";

echo "  </FORM>";

  } [COLOR=DarkOrange]// end write_login function[/COLOR]


  function verify() {

[COLOR=DarkOrange]// check to see if userid and password are valid[/COLOR]

$userid = $_POST['FormUser'];

$password = $_POST['FormPassword'];


if ($userid && $password) {   [COLOR=DarkOrange]// if both User ID and Password have been input[/COLOR]

  $db = mysql_connect("localhost", "guest", "guestpass")

  mysql_select_db("mydb") 

  $query  = "SELECT USERID FROM authen_table WHERE USERID='$userid' AND PASSWORD='$password'";

  $result = mysql_query($query);

  if (mysql_num_rows($result) == 1) {

    [COLOR=DarkOrange]// register session variable and exit the verify function[/COLOR]

    $valid_user = $userid; 

    $_SESSION['valid_user'] = $valid_user;

    return true;

  }

  else {

    [COLOR=DarkOrange]// bad userid and password[/COLOR]

    $mesg = "Access denied: User ID and Password did not match";

    write_login($mesg);

  }

  mysql_close($db);

}


else {    [COLOR=DarkOrange]// if both User ID and Password have NOT been input[/COLOR]

  $mesg = "Please login with User ID and Password";

  write_login($mesg);

}

  } [COLOR=DarkOrange]// end verify function[/COLOR]


?> 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">

<HTML>

<HEAD>

  <TITLE>Private Contents</TITLE>

</HEAD>

<BODY>


<?php

  if (verify()) {   [B][COLOR=Red]// If userid and password are valid, display the Secure Contents[/COLOR][/B]

    [COLOR=DarkOrange]// Place a button here for logging out from the Secure Contents[/COLOR]

    echo "  <FORM action=\"\" method=\"post\">";

    echo "    <INPUT type=\"submit\" value=\"Logout\">";

    echo "    <INPUT type=\"hidden\" name=\"FormLogout\" value=\"1\">";

    echo "  </FORM>";

    echo "  <P>This is some secure contents.  Please logout after finished viewing</P>";

    echo "  <P>Secure: Blah Blah Blah.</P>";

    echo "  <P>Secure: Blah Blah Blah.</P>";

    echo "  <P>Secure: Blah Blah Blah.</P>";

  }

?>


</BODY>

</HTML>

I did some research and have tried the PHP header() approach to send the no cache html headers. Something like this:

header("ETag: PUB" . time());
header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()-10) . " GMT");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 5) . " GMT");
header("Pragma: no-cache");
header("Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate");
session_cache_limiter("nocache");

But still, the problem is not resolved. I am not sure of what I am missing here.

I am new to PHP. Please kindly help solving the issue. Comments and suggestions are most welcome.

Thanks in advance.

Frustrated 😕 ,
EnVoid

    Cross-posting is frowned upon here (and just about anywhere else).

      Sorry about that... I will keep that in mind.

      I really need help to have this issue solved though.

      Thanks in advance.

      EnVoid

        Try doing a forum search, more than sure this topic has come up numerous times.

          See if changing your expires header to "Expires: -1" helps.

            Installer:

            I just gave "Expires: -1" a try, but no, that doesn't help.

              Edit: Never mind. I see you're being ably helped in your other thread. You should mark this one resolved to save people wasting time.

              I think your problem is more with program logic/structure, so I took the liberty of rewriting it a bit. Let us know how it works.

              <?php
              ob_start();
              session_start();
              ?>
              
              <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                "http://www.w3.org/TR/html4/loose.dtd">
              <HTML>
              <HEAD>
                <TITLE>Private Contents</TITLE>
              </HEAD>
              <BODY>
              
              <?php
              
              // check to see if user just logged out
              if (isset($_POST['FormLogout'])) {
                  $_SESSION = array();
                  if (isset($_COOKIE[session_name()])) {
                      setcookie(session_name(), '', time() - 42000, '/');
                  }
                  session_destroy();
                  session_start();
                  echo write_login('Login again?');
              } elseif (isset($_POST['login'])) {
                  if (verify()) {   // If userid and password are valid
                      // Place a button here for logging out 
                      echo '  <form action="" method="post">' .
                           '    <input type="submit" value="Logout" />' .
                           '    <input type="hidden" name="FormLogout" value="1" />' .
                           '  </form>' .
                           '  <p>This is some secure contents. ' .
                           '     Please logout after finished viewing</p>' .
                           '  <p>Secure: Blah Blah Blah.</p>' .
                           '  <p>Secure: Blah Blah Blah.</p>' .
                           '  <p>Secure: Blah Blah Blah.</p>';
                  } else {
                      echo write_login('Access denied: User ID and Password did not match');
                  )
              } else {
                  echo write_login('Please login with User ID and Password');
              }
              echo '</body>';
              echo '</html>';
              ob_end_flush();
              
              function write_login($mesg) 
              {
                  $str  = $mesg;
                  $str .= '  <form name="FormLogin" action="" method="post">' .
                          '    User ID:' .
                          '    <input type="text" name="FormUser" />' .
                          '    Password:' .
                          '    <input type="password" name="FormPassword" />' .
                          '    <input type="submit" name="login" value="Login" />' .
                          '  </form>';
                  return $str;
              } // end write_login function
              
              function verify() 
              {
                  // check to see if userid and password are valid
                  if (isset($_POST['FormUser']) && isset($_POST['FormPassword'])) {
                      $userid = $_POST['FormUser'];
                      $password = $_POST['FormPassword'];
                      $db = mysql_connect("localhost", "guest", "guestpass")
                      mysql_select_db("mydb") 
                      $query  = "SELECT USERID FROM authen_table " .
                                "WHERE USERID='$userid' AND PASSWORD='$password'";
                      $result = mysql_query($query);
                      if (mysql_num_rows($result) == 1) {
                          // register session variable and exit the verify function
                          $_SESSION['valid_user'] = $userid;
                          return true;
                      } else {
                          // bad userid and password
                          return false;
                      }
                      mysql_close($db);
                  } else {    // if both User ID and Password have NOT been input
                      return false;
                  }
              } // end verify function
              
              ?>

              Edit: Parse errors and others corrected.

                Installer:

                Thanks so much for your prompt reply. Unfortunately the codes you rewrote didn't work either.

                The login / logout logic works great, just like my original codes, have no problems with the login - logout - re-login parts.

                The problem still lies in the Back button response. When I log out, the browser (IE6) takes me back to the login screen. If I hit the Back button from there (without actually entering any user ID or password), the broswe gives a "Page has Expired" warning, asking me whether I want to hit the Refresh button and have the "Data re-post". If I hit yes, I will be brought back to the previous logged-in page with all secure contents showing!!

                I don't want this to happen. Imagine I hit the "Logout" button from the secure contents page, the browser takes me to the "Login again?" screen. I feel it is safe to walk off from the computer for a while. Then another user come, and all he has to do is hitting the Back button, the Refresh button and hit "Yes" in the warning dialog, then the brower will take him to the previous secure contents. He doesn't really need any user ID or password to get pass the authentication!

                Is this problem related to the browser function and we really have nothing to resolve it?

                Thanks in advance.

                Still frustrated 😕 ,
                EnVoid

                  Hi,

                  An other somewhat sexi solution.. Place a timestamp in the form, and allow * minutes for filling out the form & login.
                  If people are slower then that, just reload an empty form?

                    leatherback:

                    The problem still presists after the login - logout procedures.

                    Let's say User-A is quick enough to do the login. He sees the secure contents. Then he logs out. Now back to the login screen again. He leaves the computer. Then User-B comes to the computer and hits the Back button, boom! The secure contents are showing again without User-B submitting any login details. User-B doesn't even have to care about how quick he has to beat the login timer.

                    That's the problem.

                    EnVoid

                      THta doesn't make sense.

                      How do you keep track of a person being logged in?
                      If a person logs out, than, even with the back button, the user has to re-submit login details. Granted. These can be cached. So you add a variable in the submitted array, which is only valid for a few minutes. So after these minutes, the login procedure fails.

                      J.

                        leatherback:

                        You are right. I believe the login details are being cached. That's why I tried the expiry approach:

                        header ("Expires: Sun, 01 Nov 1970 00:00:00 GMT");  // Date in the past
                        
                        header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");  // Always modified
                        
                        header ("Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate");  // HTTP 1.1 
                        
                        header ("Pragma: no-cache");
                        
                        header("Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate");
                        
                        session_cache_limiter("nocache");
                        

                        But that doesn't help either...

                        How do you mean by adding a variable in the submitted array, which is only valid for a few minutes? I am pretty new to PHP. Please kindly explain in more details.

                        Thanks in advance.

                        EnVoid

                          The script I posted works for me with IE 6; it doesn't resubmit on the back button or ask if I want to resubmit the data, doesn't show any "protected" data, etc. So I don't know.

                            Installer:

                            Could it be someting to do with the PHP and MySQL settings on the server, or the server's cache settings?

                            If that's the case I'm afraid I have to give up...

                            EnVoid

                              Well, at least we tried to help. That's more than you can say for the other web sites you made multiple postings on.

                                Installer:

                                You are right, you guys have been very helpful. Thanks for your help. It is very much appreciated.

                                I might have to think of other approaches to resolve the problem or simply give it up.

                                One funny thing is, I tried logging out out from this forum. It says all cookies cleared. But if I hit the Back button, I am logged in again!

                                Same problem.

                                Is it just me or everyone is having the same problem too?

                                EnVoid

                                  Installer.

                                  Try back+refresh, script shows the secure content. It re-logins the user.

                                    EnVoid

                                    As far as forum logged-in is concerned. It shows that you are in logged-in state. But when you click of the secured area. It asks for the re-login.

                                    Hope This helps.

                                      joe2:

                                      It re-logins the user.

                                      As I said, it doesn't for me. I don't doubt it fails for others, I just don't know why.

                                      EnVoid:
                                      Good luck. Maybe someone else can help. I look forward to seeing you here again.

                                      As for the forum cookies, you have to translate: "all cookies cleared" is pseudo-english for "some cookies cleared".

                                        Hi envoid,

                                        THe following two lines I saw in an othe rpost. Don't know what they do, might help:

                                        Header("Cache-Control: must-revalidate");
                                        header('Cache-Control: public');
                                        J.