Jak to přihlašování vlastně funguje (session/cookie)
- Ani
- Člen | 226
Ahoj,
mám tu takový problém… Předně si potřebuju ujistit jak přihlašování v nette funguje, abych ze sebe neudělal uplnýho blbce :).
Měl jsem zato, že uživateli se vytvoří nějaký token. Ten se uloží na server společně s identitou do session (UserStorage). Uživatel má v cookies pouze tento token.
Když pak přijde uživatel na stránku třeba po týdnu z cookie se načte token „spáruje“ se s session a uživatel je přihlášen.
To je i důvod proč je nutné mít session session.gc_maxlifetime nastavenou na poměrně dlouho, třeba ten týden.
Z toho mi vychází že by mělo být celkem běžné mít na hostingu možnost session.gc_maxlifetime nastavit třeba na ten týden.
Funguje to takhle?
- Filip Procházka
- Moderator | 4668
Ten token se jmenuje SESSION ID
a hostingu je to celkem jedno,
dokud ti dovolí měnit si to na
úrovni aplikace.
- Filip Procházka
- Moderator | 4668
Tak ono jde o to, že ten garbace collector maže nepotřebná data. Kdyby jim tam každý uprdnutí trčelo dva týdny, tak se jim to nemusí líbit.
Řešit se to dá tak, že session budeš ukládat do nějaké databáze, tam ti je jedno jak je nastavený hosting.
- Tomáš Votruba
- Moderator | 1114
Díky za nakousnutí tématu. Mám s trvalým přihlášením problém. Zmíněnou direktivu jsem zkusil a vrací mi 1440, což by zhruba odpovídalo.
Má Nette pro tyto účely nějakou spešl cookie? Případně existuje nějaký doporučený způsob jak trvalé přihlášení realizovat? Díky.
- Ani
- Člen | 226
Co jsem to zkoumal tak tam nic takového není. Napadlo mě přepsat si UserStorage, ale tam je to na tu session docela vázané, takže by to chtělo asi i vlastního Usera a určitě ještě něco, nějaké čísté jednodcuhé řešení tam nevidím.
Já jsem si udělal to ISessionStorage jak zmiňuji nahoře, trochu jsem si
upravil tohle, takže teď ukládám session do sqlite:
https://forum.nette.org/…gu-a-priorit#…
btw. Já hostuju na savane, když tam dáš větší číslo jak 18 hod tak tam zůstavá výchozích 1440…
- Tomáš Votruba
- Moderator | 1114
Konečně, já taky na Savaně! :) Díky, ještě jsem koukal sem: https://forum.nette.org/…eulozi-do-db#….
Mohl bych tě požádat o tvé řešení? Zatím jsem se dostal tak daleko, že se připojím k db a něco zaznamenám. Když se ale zkusím přihlásit, tak zůstanu nepřihlášený.
Díky za návod!
Editoval Schmutzka (16. 4. 2012 1:56)
- Ani
- Člen | 226
Pužívám verzi nette 2.0.3
V bootrapu nic se session nemám, vše řeším v configu.
Start session na smart.
Jednak si nastavim sessionStorage, která se pak automaticky přidává do setStorage(), configurator ho přidá podle typehintu ISessionStorage automaticky.
No a jako druhé si vytvořim vlastní session, kde volám, už zmíněny setStorage, nějakou cestu pro db a setExpiration ta je důležitá, protože sice neovlivní session, ale nastavuje i expirace cookies, viz HosipLanem zmíněná funkce ve druhém příspěvku.
nette:
session:
autoStart: smart
services:
sessionStorage:
class: Services\SessionStorage
session:
setup:
- setStorage()
- setSavePath("%tempDir%/session.dbs")
- setExpiration(+ 30 day)
SessionStorage
<?php
namespace Services;
/**
* SessionStorage
*
*/
class SessionStorage implements \Nette\Http\ISessionStorage {
/**
* Holds the database connection
* @var \dibiConnection
*/
private $conn = null;
public function open($savePath, $sessionName) {
if (is_null($this->conn)) {
$this->conn = \dibi::connect(array('driver' => 'sqlite', 'database' => $savePath));
// \dibi::activate(MainConnectionName);
};
}
public function read($id) {
if (is_null($this->conn)) {
throw new \Nette\InvalidStateException("The connection to database for session storage is not open!");
};
$query = '
SELECT
[data]
FROM [session]
WHERE
[id] = %s';
try {
$result = $this->conn->query($query, $id);
return $result->fetchSingle();
} catch (\Exception $e) {
$this->conn->query('CREATE TABLE [session] ([id] varchar(32) not null primary key, [timestamp] timestamp not null, [data] text)');
$this->conn->query('CREATE INDEX [session_by_timestamp] ON [session] ([timestamp])');
return '';
};
}
public function write($id, $data) {
if (is_null($this->conn)) {
throw new \Nette\InvalidStateException("The connection to database for session storage is not open!");
};
$this->conn->begin();
$this->conn->query('DELETE FROM [session] WHERE [id] = %s', $id);
$this->conn->query('INSERT INTO [session] VALUES(%s, %s, %s)', $id, time(), $data);
$this->conn->commit();
}
public function destroy($id) {
if (is_null($this->conn)) {
throw new \Nette\InvalidStateException("The connection to database for session storage is not open!");
};
$this->conn->query('DELETE FROM [session] WHERE [id] = %s', $id);
}
public function clean($max) {
if (is_null($this->conn)) {
throw new \Nette\InvalidStateException("The connection to database for session storage is not open!");
};
$old = (time() - $max);
$this->conn->query('DELETE FROM [session] WHERE [timestamp] < %s', $old);
}
public function close() {
$this->conn = null;
}
public function remove($id) {
}
}
?>
Jestli se nepletu, tak nic víc jsem neměnil. Pak si to teda chce ještě nějak ošetřit to mazaní a tak, ale to přihlášení mi takhle chodí.
PS. můžeš je s tím taky otravovat na helpdesku, třeba se proberou a změní to zpět na nějou použitelnou hodnotu… :)
Editoval Ani (15. 4. 2012 20:54)
- Tomáš Votruba
- Moderator | 1114
To jsem už předevčírem, uvidíme :). Díky moc, přihlášení jede, nasadil jsem pro testovací provoz.
Je nějaké srovnání pro sqlite? Nešlo by to např. přímo v db rychleji? Ptám se, protože už po prvním přihlášení má nový soubor 14 kB.
EDIT: Aha, tak jsem to změnil v nastavení VPS a už to jde. Jen teď nevím, k čemu je potřeba vlastní třída. Pouhé nastavení VPS bez ní by trvalé přihlášení neumožnilo?
Editoval Schmutzka (16. 4. 2012 13:42)
- Ani
- Člen | 226
Jde nastavit max 64800s tj. 18 hodin a to je nedostatečné, alespoň pro mě…
DB by možná rychlejší byla, když se tam ten web už připojí, ale mě se část stránek díky cache do db vůbec nepřipojuje a tam bude rychlejší ta sqlite.
Nějaký testy a srovnaní jsem zatím neřešil. Beru to jako provizorní řešení, s tim že se uvidí co to bude dělat.
- Filip Procházka
- Moderator | 4668
Až teď jsem si to přečetl… Vy řešíte problém s nastavením VPSka? A to jako myslíte smrtelně vážně? A to jako u takového hostingu dobrovolně zůstáváte? Čím dřív přejdete, tím méně dat budete migrovat ;)
- stekycz
- Člen | 152
Zkoušel jsem tohle řešení použít upravené pro použití normální databáze a nechtělo mi to fungovat. Bylo pořeba přidat třídě destruktor asi takhle:
public function __destruct() {
session_write_close();
}
Abych pravdu řekl, tak nechápu moc proč. Dokonce i podle PHP dokumentace
by se tahle metoda měla volat při ukončení skriptu automaticky. Používám
PHP 5.3.10.
Když jsem například v Presenteru
zkusil zavolat
$this->context->session->close();
, tak mi to schodilo
Apache.
- Bernard Williams
- Člen | 207
Nazdárek,
jak prosím metodě open($savePath, $sessionName) předám objekt \Nette\Database\Connection $connection nebo aspoň config? Pouhé předání konstruktorem nestačí – nebo spíš funguje, ale jen u metod write() a remove().
Řeším to kvůli hostingu SAVANA.cz, kde se nedá nastavit potřebná životnost session.
Budu rád za každou radu nebo nápad.
Díky
Bernard