73.8.6. Přihlašování znovu a lépe

Abstrakt

Popis jakým způsobem implementovat web jehož části jsou chráněné přihlašovací procedurou.

Princip fungování je následující. Stránka, která je chráněna, si ověří, zdali je uživatel přihlášen. Jestli ano, zobrazí se normálně. Není-li uživatel přihlášen provede se přesměrování na přihlašovací stránku.

response_redirect(response, "login.kl1");

Jak poznáme že je uživatel přihlášen? Podle nastavení proměnné v session:

const char *username = session_get(session, "username");
if (username == NULL) {
    /* Uživatel není přihlášen */
    response_redirect(response, "login.kl1");
    return;
}

Samotné přihlášení je implementováno ve stránkách login.kl1 a authenticate.kl1. V login.kl1 zobrazíme jen formulář pro zadání uživatelského jména a hesla:

<html>
  ⋮
    <form action="authenticate.kl1" method="post">
        Username: <input type="text" name="username"><br/>
        Password: <input type="password" name="password"><br/>
        <input type="submit" name="login">
    </form>
  ⋮
</html>

A samotné ověření užovatele v authenticate.kl1 vypadá takto:

vars_t *args = request_get_args(request);
const char *username = NULL;
const char *password = NULL;

if (vars_get_value(args, "login")) {
        username = vars_get_value(args, "username");
        password = vars_get_value(args, "password");

	if (password_match(username, password) {
                session_set(session, "username", username);
        } else {
                session_del(session, "username");
        }
}

Zde použitá funkce password_match provádí ověření jména a hesla. Může vypadat nějak takto:

int password_match(const char *username, const char *password)
{
        if ((strcmp("radek", username) == 0) && (strcmp("heslo", password) == 0)) return -1;
        if ((strcmp("pavel", username) == 0) && (strcmp("pomeranc", password) == 0)) return -1;
	return 0
}

Pokud potřebujeme uživatele odhlásit, provádí se to odstraněním jeho uživatelského jména se session. Tedy jedná se o stejný příkaz který jsme použili v authenticate.kl1 v případě že jméno neodpovídá heslu.

session_del(session, "username");

Toto je v základu princip jak přihlášení a odhlášení funguje. Při rozpracování na konkrétní případ může kód narůst o spoustu dalších věcí. Například samostatnou stránku authenticate.kl1 můžeme zakomponovat do stránky login.kl1.

<%!  webapp/www/login.kl1
static char *username = NULL;
static char *password = NULL;
%><%
vars_t *args = request_get_args(request);

/*
 * Podle přítomnosti proměnné formuláře "login" poznáme, zdali přicházíme
 * s vyplněným username a password z tohoto formuláře.
 */
if (vars_get_value(args, "login")) {
        username = vars_get_value(args, "username");
        password = vars_get_value(args, "password");
        if (password_match(username, password)) {
                warn_if (session_set(session, "username", username));

		/*
                 * Přesměrování na původní chráněnou stránku, jestli byla zadána.
                 *  Jinak na index.kl1
                 */
                redirector = session_get(session, "redirector");
                warn_if (response_redirect(response, redirector ? redirector : "index.kl1"));
        } else {
	        warn_if (session_del(session, "username"));
        }
}
%>
<html>
  <head>
    <title>Login</title>
    ...
  </head>
  <body>
    <form action="login" method="post">
      Username: <input type="text" name="username"/><br/>
      Password: <input type="password" name="password"/><br/>
      <input type="submit", value="login"/>
    </form>
  </body>
</html>