irwan

PHP/MySQL Authentication

Nov 16th, 2011
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.33 KB | None | 0 0
  1. MySQL 5.x Stored Routines, PHP Session Values, a little CSS oh my! Complex to set up but easy to impliment. Geared toward security, simplicity (of use) and convenience.
  2.  
  3. So that's it. If you include secure1.php on any php page, the user must login to see the page. The user is logged out after 10 minutes of inactivity (the browser won't update after 10 mintues, but if they try to view a secure page, they'll be asked to login again). A secure2.php (or 3.php or 10.php) may also be created and included instead of secure1.php. A user may view pages with a security level equal to or below his own security level. I know it's a lot. I've seen other people put up their "authentication" methods to be cut to shreds. SQL Injection, etc - everyone has their own concerns. This, I feel, is a tidy way to keep things secure. The session cookie is used, but holds no user-identifiable information. You'd need to read the database to find out what the session value means, and even then, you won't get a useful password. Let me know what ya think. Peace.
  4.  
  5.  
  6.  
  7. login
  8. +---------------+-------------+------+-----+---------+----------------+
  9. | Field         | Type        | Null | Key | Default | Extra          |
  10. +---------------+-------------+------+-----+---------+----------------+
  11. | loginid       | int(11)     | NO   | PRI | NULL    | auto_increment |
  12. | loginnm       | varchar(64) | NO   |     |         |                |
  13. | password      | varchar(32) | NO   |     |         |                |
  14. | memberid      | int(11)     | NO   |     |         |                |
  15. | createddttm   | datetime    | NO   |     |         |                |
  16. | validateddttm | datetime    | YES  |     | NULL    |                |
  17. | lastlogindttm | datetime    | YES  |     | NULL    |                |
  18. | activeflg     | bit(1)      | NO   |     |         |                |
  19. | memberlevel   | int(11)     | YES  |     | NULL    |                |
  20. +---------------+-------------+------+-----+---------+----------------+
  21.  
  22. sessions
  23. +----------------+-------------+------+-----+---------+-------+
  24. | Field          | Type        | Null | Key | Default | Extra |
  25. +----------------+-------------+------+-----+---------+-------+
  26. | phpsessid      | varchar(32) | NO   | PRI |         |       |
  27. | loginid        | int(11)     | YES  |     | NULL    |       |
  28. | lastupdatedttm | datetime    | NO   |     |         |       |
  29. +----------------+-------------+------+-----+---------+-------+
  30.  
  31.  
  32. <?
  33. // db.php
  34. // This file is used to connect to the MySQL database
  35. // It also includes some useful/common database functions.
  36.  
  37. // hard-coded parameters: replace as needed for your setup
  38. $dbhost = "mysql.yourDomain.tld";
  39. $dbuser = "yourDatabaseUser";
  40. $dbpass = "yourPassword";
  41.  
  42. // dbConnect() function: called prior to making a query
  43. function dbConnect($db="yourDatabaseName") {
  44.    global $dbhost, $dbuser, $dbpass;
  45.    $dbcnx = @mysql_connect($dbhost, $dbuser, $dbpass, false, 65536)
  46.        or die("The site database appears to be down.");
  47.    if ($db!="" and !@mysql_select_db($db))
  48.        die("The site database is unavailable.");
  49.    return $dbcnx;
  50. }
  51.  
  52. // The dbparse function will format input to help
  53. // prevent SQL injection
  54. function dbparse($value)
  55. {
  56.   // Stripslashes
  57.   if (get_magic_quotes_gpc()) {
  58.     $value=stripslashes($value);
  59.   }
  60.   // Quote if not integer
  61.   if (!is_numeric($value)) {
  62.     $value = "'" . mysql_real_escape_string($value) . "'";
  63.   }
  64.   return $value;
  65. }
  66.  
  67. // The execsql function is how we call queries.
  68. // NOTE: every query I use is designed to return some values.
  69. // Null or empty recordsets will return an error.
  70. // Also note the hack around MySQL's inability to return user-defined
  71. // error codes from stored routines (the 'unknown table' hack)
  72. function execsql ($qry) {
  73.   global $errorCode,
  74.          $errorMsg;
  75.   $errorCode=0;
  76.   $errorMsg="";
  77.  
  78.   dbConnect();
  79.   $result = mysql_query($qry);
  80.   if(mysql_error()!="")
  81.   {
  82.     $errorCode = -1;
  83.     $errorMsg = mysql_error();
  84.     if(substr($errorMsg,0,15) == "Unknown table '")
  85.     {
  86.       $errorMsg = substr($errorMsg,strpos($errorMsg,"'")+1,(strlen($errorMsg)-strpos($errorMsg,"'"))-2);
  87.     }
  88.     unset($result);
  89.   }
  90.     else
  91.   {
  92.     if(!$result)
  93.     {
  94.       error("$_SERVER[PHP_SELF]\\nNo Result from query.");
  95.     }
  96.     if(mysql_num_rows($result)==0)
  97.     {
  98.       error("$_SERVER[PHP_SELF]\\nInvalid result set from query.");
  99.     }
  100.   }
  101.   return $result;
  102. }
  103.  
  104. // The "error" function: pops up a window with the error message.
  105. // I normally don't put this here, but I think it will work:
  106. function error($msg) {
  107.    ?>
  108.    <html><head>
  109.    <script language="JavaScript">
  110.    <!--
  111.        alert("<?=$msg?>");
  112.        history.back();
  113.    //-->
  114.    </script>
  115.    </head><body></body></html>
  116.    <?
  117.    exit;
  118. }
  119. ?>
  120.  
  121.  
  122. <?
  123. // hereiam.php
  124. // This script maintains entries in the sessions
  125. // table of the database.  The sessions are used
  126. // for security.
  127.  
  128. include_once 'path/to/db.php';
  129.  
  130. $myPhpsessid = isset($_COOKIE['PHPSESSID']) ? $_COOKIE['PHPSESSID'] : '';
  131. if($myPhpsessid!='') {
  132.   dbConnect();
  133.   $qry=sprintf("call prc_hereiam(%s)",dbparse($myPhpsessid));
  134.   $result=mysql_query($qry);
  135.   if(!$result)
  136.   {
  137.     error('HereIAm.php\\nNo Result from Database.');
  138.   }
  139.   $row = mysql_fetch_row($result);
  140.  
  141.   $sessionLoginId = $row[0];
  142.   $sessionMemberLevel = $row[1];
  143.  
  144. }
  145. ?>
  146.  
  147.  
  148. begin
  149.  
  150. declare outLoginId     int;
  151. declare outMemberLevel int;
  152.  
  153. DELETE
  154.   FROM sessions
  155.  WHERE lastupdatedttm <= date_add(now(),interval -10 minute);
  156.  
  157. IF((SELECT count(*) FROM sessions WHERE phpsessid=varPHPSessID)>0) then
  158.    UPDATE sessions
  159.       SET lastupdatedttm = now()
  160.     WHERE phpsessid = varPHPSessID;
  161. else
  162.    INSERT sessions (
  163.                     phpsessid,
  164.                     lastupdatedttm
  165.                    )
  166.    VALUES (
  167.            varPHPSessID,
  168.            now()
  169.           );
  170. end IF;
  171.  
  172. SELECT login.loginid,
  173.        login.memberlevel
  174.   INTO outLoginId,
  175.        outMemberLevel
  176.   FROM login,
  177.        sessions
  178.  WHERE sessions.loginid = login.loginid
  179.    AND sessions.phpsessid=varPHPSessID
  180.    AND login.activeflg = 1;
  181.  
  182. IF(isnull(outLoginId)=1) then
  183.    SET outLoginId     = 0,
  184.        outMemberLevel = 0;
  185. end IF;
  186.  
  187. SELECT outLoginId,
  188.        outMemberLevel;
  189.  
  190. commit;
  191.  
  192. end
  193.  
  194.  
  195. <?
  196. // secure1.php
  197. // The basic security: user must be logged in and have a security level
  198. // of 1 or higher.  The $securityLevel is a hack - there's definately a
  199. // better way to do this.  But for pages that require a higher security
  200. // level, this file could be coppied and $securityLevel changed to
  201. // something higher.
  202.  
  203. include_once 'path/to/hereiam.php';
  204. include_once 'path/to/processloginform.php';
  205.  
  206. $securityLevel = 1;
  207.  
  208. if($sessionLoginId==0 || $sessionMemberLevel < $securityLevel) {
  209.   if($errorMsg!="") {
  210. ?>
  211. <div class="error">
  212. <?=$errorMsg?>
  213. </div>
  214. <?
  215.   }
  216. ?>
  217. <!--
  218. This form uses div nodes and CSS to control the layout.
  219. See the CSS file to adjust the layout of the form.
  220. -->
  221. <div id="loginformdiv">
  222.   <form id="loginform" name="loginform" method="post" action="<?=$_SERVER['PHP_SELF']?>">
  223.     <div class="insideform">
  224.     <div class="loginformtitle">
  225.       <p>Members Login:</p>
  226.     </div>
  227.     <div class="loginformrow">
  228.       <div class="loginformcolleft">
  229.         Login Name:
  230.       </div>
  231.       <div class="loginformcolright">
  232.         <input type="text" name="loginname" value="<?=$formloginname?>" />
  233.       </div>
  234.     </div>
  235.     <div class="loginformrow">
  236.       <div class="loginformcolleft">
  237.         Password:
  238.       </div>
  239.       <div class="loginformcolright">
  240.         <input type="password" name="pass" value="<?=$formpassword?>"/>
  241.       </div>
  242.     </div>
  243.     <div class="loginformrow">
  244.       <div class="loginformcolleft">
  245.       </div>
  246.       <div class="loginformcolright">
  247.         <input type="submit" name="submit" value="Login" />
  248.       </div>
  249.     </div>
  250.     </div>
  251.   </form>
  252. </div>
  253.  
  254. <?
  255.   die;
  256.   // If the user is allowed to see the page, nothing is displayed.
  257. }
  258. ?>
  259.  
  260.  
  261. #loginformdiv {
  262. float: left;
  263. margin: 20px;
  264. }
  265. #loginformdiv div {
  266. margin: 0px;
  267. padding: 0px;
  268. border: 0px;
  269. }
  270. #loginform{
  271. width: 400px;
  272. border-top: 2px solid #ddd;
  273. border-left: 2px solid #ddd;
  274. border-bottom: 2px solid #999;
  275. border-right: 2px solid #999;
  276. float: left;
  277. }
  278. #loginformdiv .loginformtitle {
  279. background: #346800;
  280. color: #fff;
  281. border-bottom: 1px solid #ddd;
  282. padding-left: 20px;
  283. }
  284. #loginformdiv .loginformrow {
  285. background: #ddd;
  286. float: left;
  287. padding: 3px 0 3px 0;
  288. }
  289. #loginformdiv .loginformcolleft {
  290. width: 150px;
  291. text-align: right;
  292. float: left;
  293. }
  294. #loginformdiv .loginformcolright {
  295. width: 240px;
  296. text-align: left;
  297. float: right;
  298. }
  299. .error {
  300. color: #f00;
  301. background: #eee;
  302. width: 80%;
  303. padding: 2px;
  304. margin: 2px;
  305. border-top: 2px solid #aaa;
  306. border-left: 2px solid #aaa;
  307. border-right: 2px solid #333;
  308. border-bottom: 2px solid #333;
  309. }
  310.  
  311.  
  312. <?
  313. // processLoginForm.php
  314. // This PHP file is responsible for processing the
  315. // Login form and setting the value in the Sessions table
  316. // It is called from the secure1.php file.
  317.  
  318.   $postloginname = isset($_POST['loginname']) ? $_POST['loginname'] : '';
  319.   $postpassword  = isset($_POST['pass']) ? $_POST['pass'] : '';
  320.   $postsubmit    = isset($_POST['submit']) ? $_POST['submit'] : '';
  321.   $myPhpsessid   = isset($_COOKIE['PHPSESSID']) ? $_COOKIE['PHPSESSID'] : '';
  322.  
  323.   $formpassword  = $postpassword;
  324.   $formloginname = $postloginname;
  325.  
  326.   if($postsubmit!=""  && $postloginname!="" && $postpassword !="")
  327.   {
  328.     $qry = sprintf("call prc_login(%s, %s, %s)",
  329.            dbparse($postloginname),
  330.            dbparse($postpassword),
  331.            dbparse($myPhpsessid));
  332.     $result=execsql($qry);
  333.  
  334.     if($result)
  335.     {
  336.       $row = mysql_fetch_row($result);
  337.       $sessionLoginId     = $row[0];
  338.       $sessionMemberLevel = $row[1];
  339.     }
  340.   }
  341.  
  342. ?>
  343.  
  344.  
  345. begin
  346.  
  347. declare varLoginId int;
  348.  
  349. SELECT loginid
  350.   INTO varLoginId
  351.   FROM login
  352.  WHERE loginnm = varLoginName
  353.    AND password(varPassword) = password
  354.    AND activeflg = 1
  355.    AND validateddttm IS NOT NULL;
  356.  
  357. IF (isnull(varLoginId)) then
  358.   DROP TABLE `Error: Invalid login name or password`;
  359. end IF;
  360.  
  361. UPDATE sessions
  362.    SET loginid = varLoginId
  363.  WHERE phpsessid = varPHPSessId;
  364.  
  365. IF (isnull(varLoginId)=0) then
  366.   UPDATE login
  367.      SET lastlogindttm = now()
  368.    WHERE loginid = varLoginId;
  369. end IF;
  370.  
  371. SELECT loginid,
  372.        memberlevel
  373.   FROM login
  374.  WHERE loginid = varLoginId;
  375.  
  376. commit;
  377. end
Advertisement
Add Comment
Please, Sign In to add comment