
Autorem článku je Petr Stříbný. Programátor. Věnuje se internetovým stránkám, technologiím, jazykům C# a PHP. Při přípravě na maturitu sepsal některé maturitní otázky na web. Kromě toho si píše osobní blog.
Zařazení článku
Naše projekty
Cíle
Nedávno jsem potřeboval jednotné uživatelské účty napříč celým webem, jehož součástí mělo být i fórum. Jelikož je celkem zbytečné, pracné a drahé takové fórum naprogramovat, zvolil jsem instalaci již hotového open source produktu. V mém případě padla volba na oblíbené a hojně nasazované phpBB v jeho poslední trojkové verzi. S nasazováním softwaru třetích stran přichází samozřejmě i problémy: jak umožnit uživatelům, aby se mohli přihlásit se stejným jménem a heslem ve všech částech webu?
Pokud už používáte na webu vlastní účty a budete chtít fórum přidat k existujícímu webu, dostáváte se do celkem nepříjemné situace. Zatímco použití existujících účtů z phpBB je celkem jednoduché, přinutit fórum, aby používalo účty vaše bude mnohem obtížnější. V tomto případě bych asi doporučil účty přemigrovat do phpBB (uživatelům vygenerovat nová hesla) a dále používat účty z phpBB, jak ukážu v tomto článku.
Cílem bude na našem webu vytvořit přihlášení, odhlášení, registraci a zaslání nového hesla pomocí vlastních formulářů. Nejde mi o to, jak tyto věci udělat nejlépe, ale jak je udělat jednoduše a rychle. Pokud máte nápady na "čistší" řešení, nebojte se v komentářích ozvat.
Příprava
Pokud vaše phpBB fórum neprovozujete na subdoméně, ale jako klasickou složku (example.com/forum), můžete si ušetřit několik starostí. Protože však je použití subdomény pro fórum velice časté a protože se jednalo i o můj případ, bude se článek týkat této varianty.
Předpokládám, že máte na webu následující adresářovou strukturu:
/ - www (example.com) - forum (forum.example.com)
Je potřeba, abyste byli schopni zahrnout (pomocí include_once) do vašeho skriptu v adresáři "www" jiné skripty z adresáře "forum". Pokud pro to nemáte práva,
vykoukne na vás "open_basedir restriction" chyba. V takovém případě by mělo stačit zažádat webhosting o zrušení tohoto omezení.
K zajištění trvalého přihlášení uživatelů napříč celým webem je potřeba ukládat autentifikační cookie pouze pro jednu doménu, tak aby skript, který kontroluje přihlášení, měl vždycky k této cookie přístup (cookies se ukládají zvlášť na základě jednotlivých domén/subdomén a jednou vytvořená cookie na example.com by neplatila na fóru a naopak). Jak nastavit phpBB, aby ukládalo a načítalo cookies z example.com místo forum.example.com? Přihlašte se do administrace a v sekci "konfigurace serveru", vyberte "cookies" a tam nastavte "doménu cookie" na "example.com".
Pokud používáte jedno připojení (mysql_connect()) na začátku vašich skriptů a poté voláte mysql_query() bez parametru connection, říkáte si při integraci phpBB o problém. Jelikož budeme includovat
phpBB skripty, které si vytváří vlastní konexi k db, může se vám stát, že vaše volání mysql_query() použije místo vaši konexi tu z phpBB. Jak tomu předejít? Za prvné pojmenovat vaši konexi jinak než $db a za druhé
při volání mysql_query() využít nepovinného parametru connection. Příklad:
/www/db.php:
global $mdb;
$mdb = mysql_connect ($mdbhost, $mdbuser, $mdbpwd, true);
/www/sample.php:
require_once 'db.php';
global $mdb;
mysql_query("SELECT * FROM blabla", $mdb);
Dalším řešením je použít pro fórum i web stejnou databázi, potom vám může být jedno která z konexí se použije.
Je uživatel přihlášen?
Tento jednoduchý skript zkontroluje, zda je uživatel již přihlášený. Další parametry uživatele můžete získat v objektu $user, podívejte se, např. pomocí print_r($user).
/www/kontrola_prihlaseni.php:
// dulezita konstanta pro phpbb
define('IN_PHPBB', true);
// include dulezitych souboru
include('../forum/extension.inc');
include('../forum/common.php');
// naplni nam objekt $user podle dat v session
$user->session_begin();
// samotna kontrola je mozna dvema zpusoby
if(isset($user->data['is_registered']) && $user->data['is_registered'])
{
// je prihlaseny
}
// nebo pres
if($user->data['username'] != "Anonymous")
{
// je prihlaseny
}
Přihlášení uživatele
Klíčem k vytvoření jednoduchého přihlášení je vytvoření vlastního přihlašovacího HTML formuláře, který nasměrujeme na phpBB skript ucp.php (forum.example.com/ucp.php?mode=login).
/www/prihlaseni.php:
<form method="post" action="http://forum.example.com/ucp.php?mode=login">
<p>Jméno: <input name="username" type="text" id="username" /></p>
<p>Heslo: <input name="password" type="password" id="password" /></p>
<p><input name="redirect" value="http://example.com/prihlaseni.php" type="hidden">
<input name="login" class="mainoption" value="Přihlásit" type="submit"></p>
</form>
Formulář jako takový už nyní funguje, dokonce při správném přihlášení zajistí i přesměrování zpátky. Tento formulář má však pár nedostatků. Přesměrování, které phpBB po přihlášení použije je přes meta-refresh a uživatel během přihlašovacího procesu uvidí na několik vteřin přihlašovací formulář samotného fóra. Navíc pokud nastane nějaká chyba, uživatel zůstane na přihlašovací stránce fóra s chybovou hláškou, místo aby koukal na formulář, který jsme mu připravili my.
Pro vyřešení těchto problémů je potřeba modifikovat soubor /forum/includes/functions.php. Tam ve funkci login_box() kolem řádku 2300 najděte tuto část:
if ($result['status'] == LOGIN_SUCCESS)
{
$redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx");
$message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT'];
$l_redirect = ($admin) ? $user->lang['PROCEED_TO_ACP'] : (($redirect === "{$phpbb_root_path}index.$phpEx" || $redirect === "index.$phpEx") ? $user->lang['RETURN_INDEX'] : $user->lang['RETURN_PAGE']);
// append/replace SID (may change during the session for AOL users)
$redirect = reapply_sid($redirect);
// Special case... the user is effectively banned, but we allow founders to login
if (defined('IN_CHECK_BAN') && $result['user_row']['user_type'] != USER_FOUNDER)
{
return;
}
meta_refresh(3, $redirect);
trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>'));
}
A nahraďte ji za:
if ($result['status'] == LOGIN_SUCCESS)
{
$redirect = request_var('redirect', "{$phpbb_root_path}index.$phpEx");
$message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT'];
$l_redirect = ($admin) ? $user->lang['PROCEED_TO_ACP'] : (($redirect === "{$phpbb_root_path}index.$phpEx" || $redirect === "index.$phpEx") ? $user->lang['RETURN_INDEX'] : $user->lang['RETURN_PAGE']);
// append/replace SID (may change during the session for AOL users)
$redirect = reapply_sid($redirect);
// Special case... the user is effectively banned, but we allow founders to login
if (defined('IN_CHECK_BAN') && $result['user_row']['user_type'] != USER_FOUNDER)
{
return;
}
// Modified
redirect($redirect);
meta_refresh(3, $redirect);
trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>'));
}
else
{
// Modified
if(request_var('redirect', '', true) == 'http://example.com/prihlaseni.php')
{
redirect('http://example.com/prihlaseni.php?chyba='.$result['error_msg']);
}
}
Změněné řádky jsem označil komentářem "modified". Před funkcí meta_refresh() jsem zavolal redirect(), díky čemuž se zbavíme
té nepříjemné prodlevy při přihlašování. Druhá modifikace tohoto kódu spočívá v přidání větve "else", ve které zkontroluju, zda je
přihlašovací skript volaný z našeho formuláře a pokud ano, přesměruju nás hned zpátky. Do URL si však ještě přidám chybovou zprávu (konstantu), kterou pak můžeme použít pro
zobrazení chybové zprávy u našeho formuláře.
Tato konstanta nabývá těchto hodnot: LOGIN_ERROR_USERNAME, LOGIN_ERROR_PASSWORD nebo NO_PASSWORD_SUPPLIED. Ještě se můžete setkat s
konstantou říkající, že uživatel překročil maximální počet neúspěšných pokusů o přihlášení. V tomto případě phpBB obvykle zobrazí k formuláři ještě CAPTCHu, kterou je nutné vyplnit.
My se tímto problémem kvůli zachování jednoduchosti zabývat nebudeme, proto si v administraci nastavte maximální počet pokusů přihlášení na nulu, čímž nám překročení
limitu nikdy nenastane.
Odhlášení uživatele
/www/odhlaseni.php:
// dulezita konstanta pro phpbb
define('IN_PHPBB', true);
// include dulezitych souboru
include('../forum/extension.inc');
include('../forum/common.php');
// odhlasi uzivatele
$user->session_kill();
$user->session_begin();
Tak a to je prozatím vše. Rád bych se k problému integrace webu s phpBB 3 (hlavně vytvoření registračního formuláře) ještě vrátil. Ale radši nic neslibuju..
Článek publikován 2008-08-31 20:15:17.




Komentáře
To s tou doménou cookies ti v některém prohlížeči funguje? Podle pravidel by to mělo fungovat pouze u domén minimálně třetího řádu: http://web.archive.org/…ie_spec.html
Proto je nutné přihlášení napříč různými doménami dělat složitěji přes cross-site request forgery (mám dojem, že Google to tak u svých Google Accounts dělá).
Zdravím, já u mého reálného webu používám variantu s „www“ na začátku (tedy www.example.com). Do článku jsem to nedal, netušil jsem, že by to nemuselo fungovat.. díky za zmínku (každopádně v phpBB mám nastavení domény na variantu bez www a funguje to).
[0], [1] Tak jsem ten problém zkoumal a došel k tomuto řešení: v phpBB si jako doménu nastavte \„.example.com\“ (včetně první tečky), volbu \„ověřit prohlížeč pro větší zabezpečení sessions\“ vypněte, \„vynutit nastavení URL serveru\“ zapněte. Alespoň takto jsem to udělal já a funguje mi to v O, FF i IE. Možná se někdy dokopu a aktualizuju článek, prozatím to bude snad stačit tady.
Zdravím, tak na základě tohoto článku jsem se konečně dokopal k tomu využít nějaké přihlašování a zkusit na webu jakousi personalizaci. Jen jedna poznámka, v phpBB3 už žádný soubor extension.inc neexistuje. Asi tam zůstal po nějakém upgradu :)
Po vložení následujíchích řádků (a potřebném upravení cest) vše funguje jak má:
define(‚IN_PHPBB‘, true);
$phpbb_root_path = (defined(‚PHPBB_ROOT_PATH‘)) ? PHPBB_ROOT_PATH : ‚./‘;
$phpEx = substr(strrchr(FILE, ‚.‘), 1);
include($phpbb_root_path . ‚common.‘ . $phpEx);
[3] Díky za upřesnění, já to odněkud zkopíroval (pravděpodobně z fóra o dvojkové verzi) a blíže to nezkoumal.
Ahoj, mám problém s tímto článkem , už jen ta část po loginu, že se přeměruji zpět na web mi nejde… Pak se mi nepodařilo rozchodit ani indikátor jestli jsem lognutej .. moc se tady v tom článku nevyznám. Jak jsou dole v poznámkách různé úpravy. mohl by jste mi prosím někdo pomoci jak na to .. Děkuji velice Petr
Zdravím, napiš prosím čeho chceš přesně dosáhnout, jak vypadá struktura tvého webu a co jsi doposud udělal. Pak ti snad budu schopný pomoci.
Ahoj , chci dosáhnout toho že se na mích stránkách www.veselimevdedi.com , někdo přihlásí, stejné jméno a heslo jako na foru ale na webu podle toho jestli je to moderátor či admin bude mít různé pravomoce .. Jak vypadá struktura mého webu ? mno web je na www.veselimedvedi.com/new/ a forum je na forum.veselimedvedi.com Už mám povolené includování mezi doménou a subdoménou .. to funguje .. dále jsem udělal to zrušení chvilky fora po přihlášení ( změna kódu z článku ) , a můj kód vypadá takto .. <?php // dulezita konstanta pro phpbb define(‚IN_PHPBB‘, true); $phpbb_root_path =„/veselimedvedi.com/subdomains/forum/httpdocs/“;
$phpEx =„php“; // include dulezitych souboru //include(‚../forum/extension.inc‘); include($phpbb_root_path . ‚common.‘.$phpEx);
// naplni nam objekt $user podle dat v session $user->session_begin();
// samotna kontrola je mozna dvema zpusoby
if(isset($user->data[‚is_registered‘]) && $user->data[‚is_registered‘]) { echo „přihlášeny“; }
// nebo pres
if($user->data[‚username‘] != „Anonymous“) { echo „přihlášeny2“; } ?> <form method=„post“ action=„http://forum.veselimedvedi.com/ucp.php?mode=login“> <p>Jméno: <input name=„username“ type=„text“ id=„username“ /></p> <p>Heslo: <input name=„password“ type=„password“ id=„password“ /></p> <p><input name=„redirect“ value=„http://veselimedvedi.com/new/“ type=„hidden“> <input name=„login“ class=„mainoption“ value=„Přihlásit“ type=„submit“></p> </form>
a jakopřihlášení jde ale už mě to nevrátí zpět na web a když si přepíšu URL tak mi to nevypíše přihlášeny
Tak jsem to rozchodil,ale jediné co mi nejde je to jak po loginu , nastane návrat zase zpět na web . to mi nejde… Prostě se přihlásim .. a pak už zůstanu na fóru…
Nestiham, ale budu se snazit ti do nedele odpovedet.
Wow, prave tohle jsem hledal :) sice bude to vyuziti o neco mensi ale to nevadi ;)
Jen tak mimochodem, 2Autor: nemas ty se mnou matyku? (FI Masarna,ctvrtek 18:00 s Tomasem Motlem?)
Haha to je dobrý :-) no brácha (autor) ji nemá, ale já jo…
[10] Díky, právě že o tom nikdo pořádně nic nepíše (ani v zahraničí).. tak jsem rád, že článek splnil svůj účel. Na FI chodím, ale já mám matiku s doktorem Veselým:-) S tebou na cvika chodí brácha.
Jak na registraci zároveň i do phpBB si můžete přečíst zde: http://dev.timqui.net/…-i-do-phpbb/
Díky za článek. Praktický a pochopitelný. Pomohl mi.
Napsat komentář
Upozornění: komentáře jsou schvalovány!