Avatar
pivovary
Člen
Avatar
pivovary:

Ahoj, vytvořil jsem si stále přihlášení pomocí cookie. Ale řeším zásadní problém pokud nechám stránku otevřenou a po vypršení přihlašení kliknu na nějaký odkaz tak mně to hodí na přihlašení a pokud kliknu ještě jednou tak už je to přihlášené. Takže login se vykoná ale ještě před ním mně to stihne přesměrovat přesměrovat. Kontrolu přihlašení jsem dal do routercontrolleru před volání controlleru dané stránky viz. kod.

routercontroller­.php

/* kontrola jestli se ma uživatel automaticky logovat */
if (($_COOKIE["trvale_prihlaseni"]) AND (!$_SESSION["logged"]))
{
    $UsersManager = new UsersManager($lang);
    $UsersManager->auto_login($_COOKIE["trvale_prihlaseni"]);
}

/* předání potřebného controlleru */
$this->Controller->process($parsingURL);

UsersMananger.php autologin

public function auto_login($cookie)
{
      list($id, $token) = explode(":", $_COOKIE['trvale_prihlaseni']);   //Načte hodnoty z cookie
      $query = "
    SELECT *
    FROM `".$this->table["users"]."`, `".$this->table["users_login"]."`
    WHERE `".$this->table["users"]."`.`id` = `".$this->table["users_login"]."`.`user_id` AND `".$this->table["users_login"]."`.`user_id` = ? AND `".$this->table["users_login"]."`.`token` = ?;
    ";
      $row = Db::queryOne ($query,array($id, $token));
      if ($row)
      {
              session_regenerate_id(); // ochrana před Session Fixation
              $_SESSION["logged"] = true;
              $_SESSION["user"] = array("id"=>$row["user_id"], "login"=>$row["login"]);
      }

      $this->still_login(false, $token);

}
/* nastavi trvale prihlaseni */
public function still_login($checkbox=NULL, $token_old=NULL)
{
      $token = md5(uniqid(mt_rand(), true));
      if (($_SESSION["logged"]) AND ($checkbox))
      {
              setcookie("trvale_prihlaseni",$_SESSION["user"]["id"].":".$token, strtotime("+1 month"));
              $sql = "INSERT INTO `". $this->table["users_login"] ."` (`user_id`, `token`, `last_time`) VALUES (?,?, NOW());";
              $param = array($_SESSION["user"]["id"], $token);
              Db::query($sql, $param);
      }

      if (($_SESSION["logged"]) AND ($token))
      {
              setcookie("trvale_prihlaseni",$_SESSION["user"]["id"].":".$token, strtotime("+1 month"));
              $sql = "UPDATE `". $this->table["users_login"] ."` SET
                              `token` = ?,
                              `last_time` = NOW()
                              WHERE `token` = ?
                              ;";
              Db::query($sql, array($token, $token_old));
      }
}

Dá se to nějak ošetetřit nebo bude lepší ukládat http referrer a použít redirect?

 
Odpovědět 6.3.2015 19:43
Avatar
Marek Z.
Redaktor
Avatar
Marek Z.:

Hm, 2x tě to přesměruje? Kontroluješ ještě někde zda je uživatel přihlášen?

Tedy pokud nebude tak tě to přesměruje a až po té tě to zkontroluje pokud má cookie.

BTW: Ve funkci argument $cookie, nemusíš mít. Koukám, že globální pole voláš přímo v ní.

Nahoru Odpovědět 6.3.2015 20:10
Chybami se člověk učí, běžte se učit jinam!
Avatar
pivovary
Člen
Avatar
Odpovídá na Marek Z.
pivovary:

Ano, kontroluju ještě v předaném kontrolleru jestli je uživatel opravdu přihlášen
napr. admincontroller

if (!$_SESSION["logged"])
{
$this->redirect("login");
exit;
}

Ale to si myslím že v tom sledu jak to je by mělo být ok.
RouterController
kontrola cookie popr. prihlaseni
predani akce danemu kontroleru napr. Admincontroller a v nem
kontrola jestli je opravdu prihlasen

 
Nahoru Odpovědět 6.3.2015 20:14
Avatar
Marek Z.
Redaktor
Avatar
Odpovídá na pivovary
Marek Z.:

Tak to zkontroluj tam:

if(!$_SESSION["logged"]){
  if(($_COOKIE["trvale_prihlaseni"])){
      $UsersManager = new UsersManager($lang);
      $UsersManager->auto_login($_COOKIE["trvale_prihlaseni"]);
      $this->redirect("");  //Přesměrování na aktuální page, lepší to zakomponovat do funkce still_login()
  }else{
      $this->redirect("login");
      exit;
  }
}

Také ti doporučuji, exit; umístit do funkce redirect pod header, kterým provádíš přesměrování. Tento skript, by se měl nacházet pouze jednou v celé aplikaci, není to podmínkou, ale doporučuje se to.. :)

Nahoru Odpovědět 6.3.2015 20:20
Chybami se člověk učí, běžte se učit jinam!
Avatar
pivovary
Člen
Avatar
pivovary:

Tve řešení je dobré taky mne napadlo ale je to spíše obejítí toho že ta prvni varianta je v něčem špatně. A to bych musel mit potom v kazdem controlleru toto overeni, coz mi prijde zbytecne tam bych nechal pouze ten login pokud je vyzadovan.
Jinak ten exit mam i ve funkci redirect takze tady to zbytecne tupluju.

 
Nahoru Odpovědět 6.3.2015 20:32
Avatar
Marek Z.
Redaktor
Avatar
Odpovídá na pivovary
Marek Z.:

Ukaž tedy tu první variantu, kde to máš globálně tedy v hlavním kontroleru či routeru? Nevím, jak tvůj kód přesně vypadá.

Nahoru Odpovědět 6.3.2015 20:44
Chybami se člověk učí, běžte se učit jinam!
Avatar
pivovary
Člen
Avatar
pivovary:

Kousek z routercontroller­.php z pracovovni verze dle místního tutorialu

 protected $Controller;

  public function process($parameters)
  {
        Global $config;
    $parsingURL = $this->parseUrl($parameters[0]);
    if (($parsingURL[0] == "en") OR ($parsingURL[0] == "de"))
    {
      $lang = array_shift($parsingURL);
      $this->lang = $lang;
    }
    $actual_page = implode("/", $parsingURL);
/* home page */
    if (empty($parsingURL[0]))
    {
      $parsingURL[0] = "report";
    }
    if (($parsingURL[0] == "admin") AND ($parsingURL[1] != ""))
    {
      array_shift($parsingURL);
      $classController = $this->pomlckyDoVelbloudiNotace(array_shift($parsingURL)). "AController";
      $dir = "controllers/admin";
    }
    else
    {
      $classController = $this->pomlckyDoVelbloudiNotace(array_shift($parsingURL)). "Controller";
      $dir = "controllers";
    }
      if (file_exists($dir . "/" . $classController .".php"))
      {
        $this->Controller = new $classController;
        if (isset($lang))
        {
          $this->Controller->lang = $lang;
        }
      }
      else
      {
          $this->redirect("error404");
      }

    /* kontrola jestli se ma uživatel automaticky logovat */
    if (($_COOKIE["trvale_prihlaseni"]) AND (!$_SESSION["logged"]))
    {
        $UsersManager = new UsersManager($lang);
        $UsersManager->auto_login($_COOKIE["trvale_prihlaseni"]);
    }

    /* předání potřebného controlleru */
    $this->Controller->process($parsingURL);
    $this-data......
    .....
    $this->view = "layout";
 
Nahoru Odpovědět 6.3.2015 20:49
Avatar
Marek Z.
Redaktor
Avatar
Marek Z.:

Tak to použij pouze zde, když načítáš pohledy, tak to zkontroluješ ještě před tím a je to. 2x to není potřeba, zkontroluješ sušenku a bude.

Nahoru Odpovědět 6.3.2015 22:27
Chybami se člověk učí, běžte se učit jinam!
Avatar
pivovary
Člen
Avatar
pivovary:

tak jsem to trosku predelal ale porad zadny uspech
v danem kontroleru kde mam potrebu prihlaseni volam

$this->is_login($_SERVER["REQUEST_URI"]);

v hlavnim kontrolleru controller.php ze ktereho dedim jsem pridal

/* overeni prihlaseni */
public function is_login($url)
{
        /* kontrola jestli se ma uživatel automaticky logovat */
        if (($_COOKIE["trvale_prihlaseni"]) AND (!$_SESSION["logged"]))
        {
                $UsersManager = new UsersManager($this->lang);
                $UsersManager->auto_login();
//              $this->redirect(ltrim($url, "/"));
        }

        if (!$_SESSION["logged"])
        {
                $this->redirect("login");
        }
}

Ale problém mám pořád stejný vyhodí mně to vždy na ten login a po dalším obnovení to jde jak má. Pokud odkomentuju ten redirect tak si vytvořím smyčku při přesměrování.

 
Nahoru Odpovědět 7.3.2015 0:16
Avatar
Marek Z.
Redaktor
Avatar
Odpovídá na pivovary
Marek Z.:

Zkus toto, tohle by mohlo fungovat:

public function is_login($url){
    if(!isset($_SESSION["logged"])){  //Není zalogován
      /* kontrola jestli se ma uživatel automaticky logovat */
      if(isset($_COOKIE["trvale_prihlaseni"])){  //Existuje-li sušenka
          $UsersManager = new UsersManager($lang);
          $UsersManager->auto_login($_COOKIE["trvale_prihlaseni"]);
          $this->redirect(ltrim($url, "/"));  //tvůj přesměrovač
      }else{  //Sušenka není, přesměrujeme na login page
          $this->redirect("login");
          exit;
      }
    }
}

EDIT: A kde to testuješ 2x tak to zkus zakomentovat a testuj přihlášení pouze zde.. Resp. funkci volej tam kam to chceš.

Editováno 7.3.2015 13:19
Nahoru Odpovědět 7.3.2015 13:18
Chybami se člověk učí, běžte se učit jinam!
Avatar
David Hynek
Redaktor
Avatar
Odpovídá na pivovary
David Hynek:

Zdar...

máš hned na úvodní stránce spuštěné Session nebo se až dotazuješ?
Já měl podobný problém, a vyřešil jsem to spuštěním session hned na první stránce s PHP scriptem. Zkus to...

session_start();
Nahoru Odpovědět 7.3.2015 15:03
Čím víc vím, tím víc věcí nevím.
Avatar
pivovary
Člen
Avatar
pivovary:

Zúčastněným děkuji za pomoc, přineslo mi to spousta poznatků. Ale nakonec stačilo upravit nastaveni cookies na
z

setcookie("trvale_prihlaseni",$_SESSION["user"]["id"].":".$token, strtotime("+1 month"));

na

setcookie("trvale_prihlaseni",$_SESSION["user"]["id"].":".$token, strtotime("+1 month"), "/");

cookie se vlastně nevytvářela nikdy na stejné adrese, takže jsem ji dal vždy na celou doménu a je to bez problémů.

 
Nahoru Odpovědět  +1 7.3.2015 15:55
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 12 zpráv z 12.