Autor Zpráva
Eflyax
Profil
Ahoj,

Potřeboval bych pomoct s automatickým odhlašováním ve své webové aplikaci.
Přihlašování a odhlášení (provedené uživatelem) mi funguje.
Problém je v tom, že:
- nemám k dispozici SQL databázi (Aplikaci využíváme na intranetu bez přístupu na internet - k sql nemám přístup)
- na serveru nejsou povoleny globální proměnné (nevím jestli to to s tím nějak souvisí)

Po přihlášení uživatele se jeho jméno zapíše do textového souboru (databáze online uživatelů), až on sám klikne na Odhlásit se, je z té databáze (texťáku) vymazán.

Potřebuji tedy vyřešit, jak ho z toho textového souboru vymazat, například při nečinnosti 10 minut.
Nevím jestli by třeba nešlo využít platnost session tak, aby po vypršení platnosti se vykonal nějáký příkaz.
Zkoušel jsem využít i javascript, přesněji událost onUnload ale uživatel je odhlášen i při procházení mezi stránkami.

Mockrát děkuji za pomoc.
snake.aas
Profil
ukládat si i čas a porovnávat? ale to je řešení pro malé množství uživatelů...
mimochodem: hrozně rád bych ten kód viděl, jen moje zvědavost, mohl bys?
Eflyax
Profil
Ano, není problém :)

zde je login.php (zpracování jména a hesla z formuláře):

<?php 
session_start();
$Njmeno = $_POST['jmeno'];
$Nheslo = $_POST['heslo'];
setcookie("uzivatel", "$Njmeno", time()+86400);

if 
 
(($Njmeno == "jmeno1" && $Nheslo == "heslo1") || 
($Njmeno == "jmeno2" && $Nheslo == "heslo2") ||
($Njmeno == "jmeno3" && $Nheslo == "heslo3") ||
($Njmeno == "jmeno4" && $Nheslo == "heslo4") )
                {
            
                    $_SESSION['authuser'] = 1;
                    header("HTTP/1.1 301 Moved Permanently");
                    header("Location: index.php");
                    header("Connection: close");
                    

                      $staryobsah = file_get_contents("online.txt");
                      $soubor = fopen("online.txt", "w+");
                      fwrite($soubor, "$Njmeno \n$staryobsah" );
                      fclose($soubor);
// zde se otevře texťák a zapíše se na začátek dokumentu jeho jméno
-> to právě potřebuji zase smazat při neaktivitě

                    
                  }
?>


A zde je kód pro odhlášení (které provede sám uživatel):
<?php 
session_start();
$_SESSION['authuser'] = 0;
$jméno = $HTTP_COOKIE_VARS["uzivatel"];


 $staryobsah = file_get_contents("online.txt");
$soubor = fopen("online.txt", "w");
$obsahBezjména = Str_Replace ("$jméno \n", "", "$staryobsah");
//vymazání jména odhlašovaného z texťáku 

fwrite($soubor, "$obsahBezjména" );
fclose($soubor);
  

echo "Jsi úspěšně odhlášen! \n<br>";
echo "Nyní pokračuj na hlavní stranu: <a href='../'>Jít na hlavní stránku</a>";
?>
<?php exit(); ?>


Vše mi funguje bez problémů . Aplikaci využívá cca. 15 - 20 lidí.
S tím ukládáním času a porovnáváním si ale nevím rady :-(
Seith
Profil
Ověřuješ na nějaké stránce, je-li uživatel přihlášen? Nebo máš v texťáku pouze pro informaci kdo je přihlášen?
Eflyax
Profil
Ano, ověřuji. Při úspěšném přihlášení se uživateli nastavi session authuser na 1. Tato session je na každé stránce kontrolována. Odhlášením se vymaže jméno uživatele z texťáku a nastavi se session na 0 - je odhlášem.
Seith
Profil
Tak si do session ulož při přihlášení i čas, kdy se přihlásil - např. pomocí fce time(). Na každé další stránce, kde se kontroluje je-li přihlášen, přidej ještě kontrolu času ze session (čas v session > time()-60*10 (pro 10 minut)). Pokud je větší, zaktualizuj údaj v session o čase. Pokud tomu tam není, znamená to, že uživatel byl déle než 10 minut neaktivní, tj. odhlaš ho. Psal jsem to hodně obecně, pokud něco nechápeš, napiš.
Eflyax
Profil
Tohle chápu, děkuji. Je ale možné po vypršení platnosti vymazat uživatele z textového souboru?
Myslím, že to nejde. Není třeba jiná možnost jak udělat online stav uživatelů? Například výpis aktivních session?

Dále jsem ještě zkoušel přes javascript událost onunload - při odchodu chci uživatele přesměrovat, bohužel se to nestihne přesměrovat.
Koukám, že bez SQL to asi nepůjde.
Radovan789
Profil *
Eflyax:
Koukám, že bez SQL to asi nepůjde.
Proč by to nešlo ? Stačí udělat to co napsal Seith. Pak to může vypadat nějak takhle:

<?php 
session_start();

if ($_SESSION['time'] > time()-60*10 AND $_SESSION['authuser'] == 1) {

// A tady budeš mít kód který se provede v případě že uživatel bude 10 minut neaktivní.

$_SESSION['authuser'] = 0;
$jméno = $HTTP_COOKIE_VARS["uzivatel"];


 $staryobsah = file_get_contents("online.txt");
$soubor = fopen("online.txt", "w");
$obsahBezjména = Str_Replace ("$jméno \n", "", "$staryobsah");
//vymazání jména odhlašovaného z texťáku 

fwrite($soubor, "$obsahBezjména" );
fclose($soubor);
  

echo "Jsi úspěšně odhlášen! \n<br>";
echo "Nyní pokračuj na hlavní stranu: <a href='../'>Jít na hlavní stránku</a>";
}
?>
Seith
Profil
Radovan789:
Pak to může vypadat nějak takhle:
Ještě bych asi rozdělil podmínku a informoval uživatele co je špatně, ale to už je věc návrhu. Každopádně ještě nezapomeň (to je mířené spíš Eflyaxovi) na zaktualizování času v session pokud prošel kontrolou, jinak ho to odhlásí za 10 minut od přihlášení, což nechceme.
Radovan789
Profil *
Seith, Eflyax:
Taky problém je vtom, když uživatel zavře prohlížeč, tak ho to naodhlásí a zůstane zapsán v souboru, což nechceme. Takže se to bude muset vyřešit přes CRON.
Seith
Profil
Radovan789:
Taky problém je vtom, když ... vyřešit přes CRON.
To je pravda, nakonec se nevyhneme tomu, ukládat do textového souboru jméno i čas. Díky tomu bude asi nejlepší možnost ověřovat přihlášení uživatele čístě pomocí existence zápisu v souboru.
Seith
Profil
Eflyax:
Máš přístup k nastavení CRON? Pokud ano, napsal bych ti nějaké řešení.
Seith
Profil
Eflyax:
Mám dobrou náladu, tak jsem napsal přihlašování, kontrolu a odhlašování. Neřeší to problém na který poukázal Radovan789. Pokud máš na serveru přístup ke CRONu, ještě bych ti napsal script, kterej jednou za čas odstraní "prošlé" záznamy, anebo pokud uživatelů není moc (což předpokládám) a ty pravděpodobně chceš obsah souboru online.txt vypisovat (jinak by jsme ho neoužívali), nemusíme odstraňovat staré záznamy, pouze je při výpisu nevypíšeš.

soubor online.txt má strukturu:
jmeno:cas_posledni_aktivity;dalsi_jmeno:dalsi_cas_posledni_aktivity ...

prihlaseni.php:
<?php 
$Njmeno = $_POST['jmeno'];
$Nheslo = $_POST['heslo'];

if 
(($Njmeno == "jmeno1" && $Nheslo == "heslo1") || 
($Njmeno == "jmeno2" && $Nheslo == "heslo2") ||
($Njmeno == "jmeno3" && $Nheslo == "heslo3") ||
($Njmeno == "jmeno4" && $Nheslo == "heslo4") )
{

  //ulozim si jmeno uzivatele do session
  session_start();
  $_SESSION['jmeno'] = $Njmeno;
                   
  $staryobsah = file_get_contents("online.txt");
  $soubor = fopen("online.txt", "w");
  
  //zkusim zaktualizovat cas posledni aktivity v souboru, pokud se uzivatel
  //prihlasuje a je v souboru z minula (napr. neodhlasil se)
  $zaktualizovano = preg_replace("/".$Njmeno.":\d+;/U", $Njmeno.":".time().";", $staryobsah, 1, $pocet);
  
  //pokud pocet zmenenych zaznamu == 0
  if($pocet == 0){
    //neni v souboru, takze ulozime novy zaznam (jmeno s aktualnim casem)
    fwrite($soubor, $Njmeno.":".time().";".$staryobsah);
    fclose($soubor);
  }else{
    //je v souboru, takze jenom ulozime zaktualizovany udaj o case
    fwrite($soubor, $zaktualizovano);
    fclose($soubor);
  }
  
  //presmerujeme na chraneny obsah
  header("Location: stranka.php");
}else{
  echo "Špané heslo nebo jméno."
}
?>


kontrola.php:
<?php
  //vytahneme si jmeno ze session
  session_start();
  $Njmeno = $_SESSION['jmeno'];
  
  $staryobsah = file_get_contents("online.txt");
  
  //nacteme udaj o case ze zaznamu, ktery odpovida jmenu uzivatele
  if(preg_match("/$Njmeno:(\d+);/U", $staryobsah, $matches)){
    //cas je v $matches[1]
    if($matches[1]>time()-60*10){
      //pokud je aktivni, zaktualizujeme cas posledni aktivity v zaznamu a ulozime
      $zaktualizovano = str_replace("$Njmeno:$matches[1];", $Njmeno.":".time().";", $staryobsah);
      $soubor = fopen("online.txt", "w");
      fwrite($soubor, $zaktualizovano);
      fclose($soubor);
    }else{
      //pokud byl neaktivni dele nez 10 minut, presmerujeme ho na odhlaseni
      header("Location: odhlasit.php?duvod=neaktivita");
    }
  }else{
    //pokud nebyl nalezen zaznam v souboru, stranka odhlasit.php mu sdeli, ze neni prihlasen
    header("Location: odhlasit.php?duvod=neprihlasen");
  }
?>


odhlasit.php:
<?php
  //je-li duvodem to, ze neni prihlasen, sdelime to mu to
  if(isset($_GET["duvod"]) && $_GET["duvod"] == "neprihlasen"){
    echo "Nejste přihlášen, prosím přihlaste se.";
  }else{
    //jinak odhlasime
    session_start();
    $Njmeno = $_SESSION['jmeno'];
    
    $staryobsah = file_get_contents("online.txt");
    
    //odstranime zaznam
    $odstraneno = preg_replace("/".$Njmeno.":\d+;/U", "", $staryobsah, 1);
    $soubor = fopen("online.txt", "w");
    fwrite($soubor, $odstraneno);
    fclose($soubor);
    
    //pokud byla duvodem odhlaseni neaktivita, sdelime mu to 
    if(isset($_GET["duvod"]) && $_GET["duvod"] == "neaktivita"){
      echo "Byl jste odhlášen z důvodu neaktivity, prosím přihlaste se.";
    }else{
      //jinak se jednalo o normalni odhlaseni
      echo "Byl jste úspěšně odhlášen.";
    }
  }
?>


Script kontrola.php vložíš na začátek každé chráněné stránky. Pro regulerní odhlášení slouží odhlasit.php.
Eflyax
Profil
Hmm, pěkná práce, funguje to hezky. Co když uživatel se sám neodhlásí a jenom zavře prohlížeč? Zkoušel jsem to a neodhlásilo mě to.

EDIT: Mohl bych třeba použít skript, který by otevřel texťák, načetl si obsah, rozdělil si jméno a čas (přes explode) a vypsal by pak jen jména s určitým časem. Jdu to vyzkoušet.
Seith
Profil
Eflyax:
Mohl bych třeba použít skript, který by otevřel texťák, načetl si obsah, rozdělil si jméno a čas (přes explode) a vypsal by pak jen jména s určitým časem. Jdu to vyzkoušet.
Ano, to jsem měl na mysli.
Eflyax
Profil
Zkusil jsem ten skript vytvořit a na 80% to funguje jak si představuju, bohužel je tam zase jeden problém.
Použil jsem přihlašování od Seitha - všechno v pořádku.
Napsal jsem si skript, který by mi měl vypisovat všechny uživatele, co jsou online (za posledních 10 sekund).
Problém mám tenhle:
Přihlásí se uživatel1... mezitím se přihlásí uživatel2... oba jsou online, skript funguje.
Pokud ale uživatel2 je 10 sekund neaktivní, neměl by ho skript vypsat - on ale nevypíše nikoho.
I přes to, že uživatel1 je pořád přihlášený a aktivní, kvůli uživateli2 není jakoby nikdo online.

Můj skript vypis.php:
<?

$soubor = File('online.txt');
foreach ($soubor as $z)
          {
            List($Njmeno, $cas) = Explode(':',$z); // <-- podle mě je problém někde tady

 // v souboru online.txt rozdělí data na jméno a čas...
          }

   if(time() - $cas <= 10 )
   
//...od aktuálního času odečtu čas aktivity uživatele - pokud je to více jak 10 sekund, 
// je neaktivní a nechci ho vypsat.
    
    {
      $file = fopen("online.txt","r");
      $obsah = fread($file,filesize("online.txt"));
      fclose($file);
      echo ($obsah);
     // mělo by to vypsat online uživatele za posledních 10 sekund 
     //(vypíše se jméno uživatele i s jeho časem ale to mi zas tak nevadí)

    }

  else
      echo "Nikdo není online";
?>


Stručně řečeno, výpis aktivních uživatelů závisí na jednom uživateli.
Potřebuji aby se to u každého jména ověřilo zvlášť. :-(
Seith
Profil
Zkus tohle:
<?php
  $obsah = file_get_contents("online.txt");
  $zaznamy = explode(";", $obsah);
  unset($zaznamy[count($zaznamy)-1]);
  foreach($zaznamy as $zaznam){
    $zaznam = explode(":", $zaznam);
    if ($zaznam[1] > time()-10*60){
      echo $zaznam[0]."<br>";
    } 
  }   
?>
Eflyax
Profil
Jó, to je to, co potřebuju. Teď jsem spokojen na 110% ! Moc moc ti děkuju, opravdu jsi mi pomohl.
Seith
Profil
Eflyax:
Díky, rád jsem pomohl, můžu vědět co to stavíš?
Eflyax
Profil
Seith:
Řekněme systém (v intranetu), kam se můžou přihlásit lidé a můžou spolu komunikovat i bez internetu.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: