» »

Samodejna odjava uporabnika iz spletne strani - razlog??

Samodejna odjava uporabnika iz spletne strani - razlog??

Piqui ::

Hello.

Torej, vsakic znova se zataknem ob problem, da mi na spletni strani po prijavi uporabnika samodejno odjavi, če se na katerikoli podstrani (ki pač preverja status prijave) stran "na hitro" osvezi - torej refresha recimo 3x zaporedoma, preden je v celoti naložena.
Problem se pojavlja ko je na strani prisotna koda, ki preko funkcije pregleduje status uporabnika.

Prilagam funkcije, ki so sicer v datoteki functions.php, ter tisti del, ki ga implementiram direktno na stran, ki funkcijo za login check tudi poklice.

Če kdo slučajno ve, kaj bi lahko bil vzrok, please, let me know! Hvala.


Functions.php:

<?php function <strong>sec_session_start()</strong> {
        $session_name = 'sec_session_start'; // Set a custom session name
        $secure = false; // Set to true if using https.
        $httponly = true; // This stops javascript being able to access the session id. 
        ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies. 
        $cookieParams = session_get_cookie_params(); // Gets current cookies params.
        session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
        session_name($session_name); // Sets the session name to the one set above.
        session_start(); // Start the php session
        session_regenerate_id(true); // regenerated the session, delete the old one.     
}
function login($email, $password, $mysqli) {
   // Using prepared Statements means that SQL injection is not possible. 
   if ($stmt = $mysqli->prepare("SELECT ID, Username, Password, Salt FROM Users WHERE Email = ? LIMIT 1")) { 
      $stmt->bind_param('s', $email); // Bind "$email" to parameter.
      $stmt->execute(); // Execute the prepared query.
      $stmt->store_result();
      $stmt->bind_result($user_id, $username, $db_password, $salt); // get variables from result.
      $stmt->fetch();
      $password = hash('sha512', $password.$salt); // hash the password with the unique salt.
 
      if($stmt->num_rows == 1) { // If the user exists
         // We check if the account is locked from too many login attempts
         if(checkbrute($user_id, $mysqli) == true) { 
            // Account is locked
            // Send an email to user saying their account is locked
            return false;
         } else {
         if($db_password == $password) { // Check if the password in the database matches the password the user submitted. 
            // Password is correct!
 
 
               $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
 
               $user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
               $_SESSION['user_id'] = $user_id; 
               $username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); // XSS protection as we might print this value
               $_SESSION['username'] = $username;
               $_SESSION['login_string'] = hash('sha512', $password.$user_browser);
               // Login successful.
               return true;    
         } else {
            // Password is not correct
            // We record this attempt in the database
            $now = time();
            $mysqli->query("INSERT INTO Login_Attempts (UserID, Time) VALUES ('$user_id', '$now')");
            return false;
         }
      }
      } else {
         // No user exists. 
         return false;
      }
   }
}
function checkbrute($user_id, $mysqli) {
   // Get timestamp of current time
   $now = time();
   // All login attempts are counted from the past 2 hours. 
   $valid_attempts = $now - (2 * 60 * 60); 
 
   if ($stmt = $mysqli->prepare("SELECT Time FROM Login_Attempts WHERE USERID = ? AND Time > '$valid_attempts'")) { 
      $stmt->bind_param('i', $user_id); 
      // Execute the prepared query.
      $stmt->execute();
      $stmt->store_result();
      // If there has been more than 5 failed logins
      if($stmt->num_rows > 5) {
         return true;
      } else {
         return false;
      }
   }
}
function <strong>login_check($mysqli)</strong> {
   // Check if all session variables are set
   if(isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string'])) {
     $user_id = $_SESSION['user_id'];
     $login_string = $_SESSION['login_string'];
     $username = $_SESSION['username'];
 
     $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
 
     if ($stmt = $mysqli->prepare("SELECT Password FROM Users WHERE ID = ? LIMIT 1")) { 
        $stmt->bind_param('i', $user_id); // Bind "$user_id" to parameter.
        $stmt->execute(); // Execute the prepared query.
        $stmt->store_result();
 
        if($stmt->num_rows == 1) { // If the user exists
           $stmt->bind_result($password); // get variables from result.
           $stmt->fetch();
           $login_check = hash('sha512', $password.$user_browser);
           if($login_check == $login_string) {
              // Logged In!!!!
              return true;
           } else {
              // Not logged in
              return false;
           }
        } else {
            // Not logged in
            return false;
        }
     } else {
        // Not logged in
        return false;
     }
   } else {
     // Not logged in
     return false;
   }
}
?>



To pa potem dodam na vsaki strani, da kliče iz implementiranega functions.php:

<?php 
include 'db_con.php';     // samo povezava z MySql
include 'functions.php';  // zgornja datoteka
sec_session_start();
if(login_check($mysqli) == true) {
$isloggedin = true;
}
?>



To je praktično to....



Lp in hvala. M.

Piqui ::

Torej nihče, niti ideje ali sledi o tem, zakaj bi 3-je refreshi končali sejo? ://

technolog ::

Brez da bi gledal kodo, lahko na prvo žogo rečem, da je najbolj verjetno, da ti dva zahtevka padeta v isto sekundo (imata torej isti timestamp) in naredita štalo.

Probaj še v vrstici "session_regenerate_id(true);" vržt vn "true".

Just a thoutht.

Piqui ::

Mu mater!
Tvoja just a thought je tista thought, ki je rešila problem. :S
Z session_regenerate_id(false) osvezevanje ne prekine vec seje. Ocitno je res, kar si rekel, da padeta dva ali vec zahtevkov v isti sekundi in naredi zmedo, čeprav bi regenerate moral staro zbrisat....?

Kaj naj rečem, HVALA. Me pa vseeno zanima, če morda veš, zakaj je in the first place sploh zraven ukaz za regenerirat sejo?
Kode namrec nisem pisal sam, je spravljena ven iz par vodičev na internetnih straneh, ker ne poznam tako dobro še phpja...
In, kakšen efekt, (razen da zdej ocitno dela prav?) imam s tem, ko mi seje vec ne regenerira?

Se enkrat hvala,

Lp. Marko

technolog ::

Očitno se ukaz, da regenerira session ID kliče v vsakem zahtevku. To ni kul, lahko vržeš ven, celotno.

To funkcijo kliči le takrat, ko user trenutne seje poveča privilegije, torej

neprijavljen uporabnik -> prijavljen uporabnik
uporabnik, ki nima omogočene storitve -> uporabnik, ki jo ma.

To je potrebno delat zaradi napada, ki se mu reče Session Fixation, torej fiksiranje seje. Če te zanima več, si poglej na wikipediji.

Zgodovina sprememb…

Piqui ::

Ja, saj v prav zadnjem delu kode, ki je prilepljen spodaj, lahko vidis, da sem (po navodilih enega od vodicev) na vsaki strani zgoraj najprej dodal sec_session_start() , potem pa preverim login_check.

Torej, po tej logiki, če sem prav razumel, lahko pustim regenerate_session_id na true, in odstranim iz vsake strani celo funkcijo sec_session_start()?? In to potem kličem samo na loginu, in če se spremenijo privilegiji, to drzi?

Aha, ja, mislim da zdej razumem, kaj je to (thanks to wiki). Ampak, ok, kolikšne so dejanske možnosti za take napade v praksi? Mislim, konec koncev nimam banke, tako da, bolj dvomim da bi se kdo spravil v to. Kljub temu, pa da vprašam, če morda veš: Je tak napad možen v mojem primeru potem, če takoj po loginu, oz že sam login postopek pokliče regenerate_Session_id? Najbrž ne, kajne?


Res hvala ti za pomoč! :)

technolog ::

Odstrani regeneracijo v celoti, ker se ne sme izvajat ob vsakem requestu. Če boš to delal, si boš zabasal server in imel boš ta problem, ki si ga videl, da se ti sejni IDji prepisujejo.

Se pravi, poenostavljeno, 10. vrstico daj ven oz. jo prestavi v funkcijo login().

Session Fixation je dejansko zelo lahko izvedljiv v praksi. Sploh na kakih javnih računalnikih.

Tvoja koda tudi sicer ni biser, ampak bo šlo z leti na bolje :)

Zgodovina sprememb…

Piqui ::

Razumem. Ampak, torej jaz odstranim samo regenerate ven iz funkcije session start, to (session start) pa vseeno klicem vedno znova, na vsaki strani???
Ali pa lahko session start klicem samo ob loginu, in potem na vsaki strani zgolj preverjam tisti login_check..??


Heheh, ja, upajmo da bo res. ;) Nekje je pac treba zacet :P

technolog ::

session_start() kličeš na vseh straneh, kjer uporabiš, torej bodisi bereš bodisi pišeš, spremenljivko $_SESSION. Se pravi v tvojem primeru najbrž vedno.

Zaenkrat samo poprav to, kar sem ti reku, več pa kdaj drugič. Ker v kodi imaš itak 3/4 nepotrebnih stvari. Koda za login je v php največ 20 vrstic.

Zgodovina sprememb…

Piqui ::

Ok. Zmenjeno. :)

HVALA! :) Iz srca.. ;)


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

implementacija sprememb z wordpress localhost strani na wordpress stran na strežniku

Oddelek: Izdelava spletišč
6899 (758) b0jan89
»

Iskalni niz iz "Search" v "Išči"

Oddelek: Izdelava spletišč
6804 (579) Dr.S
»

Wordpress - negre odpreti wp-admin

Oddelek: Izdelava spletišč
141799 (1431) cosa nostra
»

bbpress admin

Oddelek: Izdelava spletišč
7885 (759) bole80
»

Wordpress dostop

Oddelek: Izdelava spletišč
5784 (694) Gandalfar

Več podobnih tem