Integrace webu s phpBB 3: přihlášení a odhlášení uživatelů

V mém prvním článku o integraci phpBB 3 se podíváme na způsob jak přihlásit a odhlásit již vytvořené uživatelské účty.


Petr Stříbný

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.

Naše projekty

Angličtina AGJ.cz
Dějepis


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.


Linkovat Přidat odkaz na del.icio.us

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.ar­chive.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á).

LLook

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).

Petr Stříbný

[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.

Petr Stříbný

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_ro­ot_path . ‚common.‘ . $phpEx);

Petr Patočka

[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.

Petr Stříbný

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

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.

Petr Stříbný

Ahoj , chci dosáhnout toho že se na mích stránkách www.veselimev­dedi.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.veselimed­vedi.com/new/ a forum je na forum.veselimed­vedi.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 =„/veselimed­vedi.com/subdo­mains/forum/httpdoc­s/“;

$phpEx =„php“; // include dulezitych souboru //include(‚.­./forum/exten­sion.inc‘); include($phpbb_ro­ot_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_re­gistered‘]) && $user->data[‚is_re­gistered‘]) { echo „přihlášeny“; }

// nebo pres

if($user->data[‚username‘] != „Anonymous“) { echo „přihlášeny2“; } ?> <form method=„post“ action=„http://­forum.veselimed­vedi.com/ucp.php?mo­de=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://ve­selimedvedi.com/new/“ type=„hidden“> <input name=„login“ class=„mainop­tion“ 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

Petr

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…

Petr

Nestiham, ale budu se snazit ti do nedele odpovedet.

Petr Stříbný

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?)

Fafner

Haha to je dobrý :-) no brácha (autor) ji nemá, ale já jo…

Josef Strzibny

[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.

Petr Stříbný

Jak na registraci zároveň i do phpBB si můžete přečíst zde: http://dev.tim­qui.net/…-i-do-phpbb/

dev.timqui.net

Díky za článek. Praktický a pochopitelný. Pomohl mi.

Popelka

Napsat komentář

Upozornění: komentáře jsou schvalovány!




Napište prosím, kolik je 10 bez pěti:


Náhled

Nepřehlédněte

© 2005—2007 Zápisník programátorů. Veškerá práva vyhrazena.
O zápisníku — Autoři — Archív