File: Zend_Auth_Adapter_DbTable.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (366 lines) | stat: -rw-r--r-- 14,390 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.auth.adapter.dbtable">
    <title>Uwierzytelnianie w oparciu o tabelę bazy danych</title>
    <sect2 id="zend.auth.adapter.dbtable.introduction">
        <title>Wprowadzenie</title>
        <para>
            <classname>Zend_Auth_Adapter_DbTable</classname> zapewnia możliwość
            przeprowadzenia uwierzytelniania w oparciu o dane przechowywane w
            tabeli bazy danych. Z tego względu, że klasa
            <classname>Zend_Auth_Adapter_DbTable</classname> wymaga przekazania instancji
            klasy <classname>Zend_Db_Adapter_Abstract</classname> do jej konstruktora,
            każda ta instancja jest powiązana z konkretnym połączeniem do bazy
            danych. Inne opcje konfiguracyjne mogą być ustawione za pomocą
            konstruktora lub za pomocą metod instancji, po jednej dla każdej z
            opcji.
        </para>

        <para>
            Dostępne opcje konfiguracyjne to:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <emphasis>tableName</emphasis>: Jest to nazwa tabeli bazy
                    danych, która zawiera dane uwierzytelniania i do której
                    jest przeprowadzane zapytanie uwierzytelniające.
                </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>identityColumn</emphasis>: Jest to nazwa kolumny
                    tabeli bazy danych, która reprezentuje tożsamość.
                    Kolumna tożsamości musi zawierać unikalne wartości,
                    na przykład takie jak nazwa użytkownika czy adres
                    e-mail.
                </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>credentialColumn</emphasis>: Jest to nazwa kolumny
                    tabeli bazy danych, która reprezentuje wartość
                    uwierzytelniającą. W prostym schemacie uwierzytelniania
                    opartym o nazwę tożsamości i hasło, wartość
                    uwierzytelniająca odpowiada hasłu. Zobacz także opcję
                    <emphasis>credentialTreatment</emphasis>.
                </para>
            </listitem>
            <listitem>
                <para>
                    <emphasis>credentialTreatment</emphasis>: W wielu przypadkach,
                    hasło i inne wrażliwe dane są zszyfrowane, haszowane,
                    zakodowane lub w inny sposób przetworzone przez
                    jakąś funkcję lub algorytm. Określając metodę
                    przerobienia danych, taką jak na przykład
                    'MD5(?)' czy 'PASSWORD(?)',
                    programista może użyć konkretnej funkcji SQL na danych
                    uwierzytelniających. Z tego względu, że te funkcje są
                    specyficzne dla konkretnych systemów baz danych, zajrzyj
                    do odpowiednich dokumentacji aby sprawdzić dostępność
                    takich funkcji dla twojego systemu bazy danych.
                </para>
            </listitem>
        </itemizedlist>

        <example id="zend.auth.adapter.dbtable.introduction.example.basic_usage">
            <title>Podstawowe użycie</title>
            <para>
                Jak wyjaśniono we wprowadzeniu, konstruktor klasy
                <classname>Zend_Auth_Adapter_DbTable</classname> wymaga przekazania mu
                instancji klasy <classname>Zend_Db_Adapter_Abstract</classname>,
                zapewniającej połączenie do bazy danych, z którym powiązana jest
                instancja adaptera uwierzytelniania. Na początku powinno być
                utworzone połączenie do bazy danych.
            </para>

            <para>
                Poniższy kod tworzy adapter bazy danych przechowywanej w pamięci,
                tworzy prostą strukturę tabeli, a następnie wstawia wiersz, w
                oparciu o który przeprowadzimy później zapytanie
                uwierzytelniające. Ten przykład wymaga dostępnego rozszerzenia
                PDO SQLite:
            </para>

            <programlisting language="php"><![CDATA[
// Tworzymy połączenie do bazy danych SQLite przechowywanej w pamięci
$dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
                                                  ':memory:'));

// Budujemy zapytanie tworzące prostą tabelę
$sqlCreate = 'CREATE TABLE [users] ('
           . '[id] INTEGER  NOT NULL PRIMARY KEY, '
           . '[username] VARCHAR(50) UNIQUE NOT NULL, '
           . '[password] VARCHAR(32) NULL, '
           . '[real_name] VARCHAR(150) NULL)';

// Tworzymy tabelę z danymi uwierzytelniania
$dbAdapter->query($sqlCreate);

// Budujemy zapytanie wstawiające wiersz, dla którego możemy przeprowadzić
// próbę uwierzytelniania
$sqlInsert = "INSERT INTO users (username, password, real_name) "
           . "VALUES ('my_username', 'my_password', 'My Real Name')";

// Wstawiamy dane
$dbAdapter->query($sqlInsert);
]]></programlisting>

            <para>
                Gdy połączenie do bazy danych oraz dane w tabeli są już
                dostępne, możesz utworzyć instancję klasy
                <classname>Zend_Auth_Adapter_DbTable</classname>. Opcje konfiguracyjne
                mogą być przekazane do konstruktora lub przekazane jako
                parametry do metod dostępowych już po utworzeniu instancji:
            </para>

            <programlisting language="php"><![CDATA[
// Konfigurujemy instancję za pomocą parametrów konstruktora
$authAdapter = new Zend_Auth_Adapter_DbTable(
    $dbAdapter,
    'users',
    'username',
    'password'
);

// ...lub konfigurujemy instancję za pomocą metod dostępowych
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter
    ->setTableName('users')
    ->setIdentityColumn('username')
    ->setCredentialColumn('password')
;
]]></programlisting>

            <para>
                W tym momencie intancja adaptera uwierzytelniania jest gotowa
                do przeprowadzenia zapytań uwierzytelniających. W celu
                utworzenia zapytania, wejściowe dane uwierzytelniania
                są przekazywane do adaptera przed wywołaniem metody
                <methodname>authenticate()</methodname>:
            </para>

            <programlisting language="php"><![CDATA[
// Ustawiamy wartości danych uwierzytelniania (np., z formularza logowania)
$authAdapter
    ->setIdentity('my_username')
    ->setCredential('my_password');

// Przeprowadzamy zapytanie uwierzytelniające, zapisując rezultat
$result = $authAdapter->authenticate();
]]></programlisting>

            <para>
                Oprócz możliwości użycia metody <methodname>getIdentity()</methodname>
                obiektu rezultatu uwierzytelniania, obiekt
                <classname>Zend_Auth_Adapter_DbTable</classname> pozwala także na
                odebranie wiersza tabeli po udanym uwierzytelnieniu.
            </para>

            <programlisting language="php"><![CDATA[
// Wyświetlamy tożsamość
echo $result->getIdentity() . "\n\n";

// Wyświetlamy wiersz rezultatów
print_r($authAdapter->getResultRowObject());

/* Wyświetlone dane:
my_username

Array
(
    [id] => 1
    [username] => my_username
    [password] => my_password
    [real_name] => My Real Name
)
*/
]]></programlisting>

            <para>
                Z tego względu, że wiersz tabeli zawiera dane potrzebne do
                uwierzytelniania, ważne jest, aby dane były zabezpieczone przed
                dostępem przez osoby nieuprawnione.
            </para>

        </example>
    </sect2>
    <sect2 id="zend.auth.adapter.dbtable.advanced.storing_result_row">
        <title>Zaawansowane użycie: Stałe przechowywanie obiektu DbTable Result</title>
        <para>
            Domyślnie <classname>Zend_Auth_Adapter_DbTable</classname> po udanym
            uwierzytelnieniu zwraca do obiektu uwierzytelniającego spowrotem
            tę samą tożsamość. W innym przykładzie użycia programista może
            chcieć przechować w stałym mechanizmie przechowywania
            <classname>Zend_Auth</classname> obiekt tożsamości zawierający inne użyteczne
            informacje. W takim przypadku może użyć metody
            <methodname>getResultRowObject()</methodname> aby zwrócić obiekt klasy
            <classname>stdClass</classname>. Poniższy kod ilustruje sposób jego użycia:
        </para>

        <programlisting language="php"><![CDATA[
// uwierzytelniamy za pomocą Zend_Auth_Adapter_DbTable
$result = $this->_auth->authenticate($adapter);

if ($result->isValid()) {

    // przechowujemy tożsamość jako obiekt, w którym zwracane są jedynie
    // pola username oraz real_name
    $storage = $this->_auth->getStorage();
    $storage->write($adapter->getResultRowObject(array(
        'username',
        'real_name'
    )));

    // przechowujemy tożsamość jako obiekt, w którym kolumna zawierająca
    // hasło została pominięta
    $storage->write($adapter->getResultRowObject(
        null,
        'password'
    ));

    /* ... */

} else {

    /* ... */

}
]]></programlisting>
    </sect2>
    <sect2 id="zend.auth.adapter.dbtable.advanced.advanced_usage">
        <title>Przykład zaawansowanego użycia</title>
        <para>
            O ile głównym przeznaczeniem komponentu <classname>Zend_Auth</classname> 
            (i odpowiednio <classname>Zend_Auth_Adapter_DbTable</classname>) jest
            <emphasis>uwierzytelnianie</emphasis> a nie <emphasis>autoryzacja</emphasis>,
            jest kilka problemów które możemy rozwiązać odrobinę przekraczając
            pole zastosowań komponentu. Zależnie od tego jak zdecydujesz
            wyjaśnić swój problem, czasem może być przydatne rozwiązanie
            problemu autoryzacji podczas uwierzytelniania.
        </para>

        <para>
            Komponent <classname>Zend_Auth_Adapter_DbTable</classname> posiada 
            pewien wbudowany mechanizm, który może być użyty do dodania dodatkowych 
            warunków podczas uwierzytelniania, dzięki czemu można rozwiązać niektóre
            problemy.
        </para>

        <programlisting language="php"><![CDATA[
// Wartość pola "status" dla tego konta nie jest równa wartości "compromised"
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    'MD5(?) AND status != "compromised"'
);

// Wartość pola "active" dla tego konta jest równa wartości "TRUE"
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    'MD5(?) AND active = "TRUE"'
);
]]></programlisting>

        <para>
            Innym przykładem może być implementacja mechanizmu saltingu. Jest to
            technika pozwalająca w znaczny sposób zwiększyć bezpieczeństwo
            aplikacji. Polega ona na tym, że dołączając do każdego hasła losowy
            łańcuch znaków spowodujemy, że niemożliwe będzie przeprowadzenie
            ataku brute force na bazę danych w oparciu o przygotowany słownik.
        </para>

        <para>
            Zaczniemy od zmodyfikowania schematu tabeli bazy danych, aby móc
            przechowywać nasz łańcuch znaków salt:
        </para>

        <programlisting language="php"><![CDATA[
$sqlAlter = "ALTER TABLE [users] "
          . "ADD COLUMN [password_salt] "
          . "AFTER [password]";

$dbAdapter->query($sqlAlter);
]]></programlisting>

        <para>
            W prosty sposób wygenerujmy salt dla każdego rejestrującego się
            użytkownika:
        </para>

        <programlisting language="php"><![CDATA[
for ($i = 0; $i < 50; $i++)
{
    $dynamicSalt .= chr(rand(33, 126));
}
]]></programlisting>

        <para>
            I skonfigurujmy sterownik bazy danych:
        </para>

        <programlisting language="php"><![CDATA[
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    "MD5(CONCAT('"
    . Zend_Registry::get('staticSalt')
    . "', ?, password_salt))"
);
]]></programlisting>
        <note>
            <para>
                Możesz jeszcze zwiększyć bezpieczeństwo używając dodatkowo
                statycznego fragmentu łańcucha znaków umieszczonego na stałe
                w kodzie aplikacji. W przypadku, gdy atakujący uzyska dostęp
                do bazy danych (np. za pomocą ataku <acronym>SQL</acronym> 
                injection), a nie będzie miał dostępu do kodu źródłowego, 
                hasła wciąż będą dla niego nieprzydatne.
            </para>
        </note>

        <para>
            Innym sposobem jest użycie metody <methodname>getDbSelect()</methodname> 
            klasy <classname>Zend_Auth_Adapter_DbTable</classname> po utworzeniu
            adaptera. Ta metoda zwróci obiekt klasy <classname>Zend_Db_Select</classname>, 
            który ma być użyty do przeprowadzenia uwierzytalniania. Ważne jest, że
            ta metoda zawsze zwróci ten sam obiekt, niezależnie od tego czy metoda
            <methodname>authenticate()</methodname> została wywołana czy nie.
            Ten obiekt <emphasis>nie będzie</emphasis> posiadał żadnych informacji
            dotyczących nazwy tożsamości i hasła, ponieważ te dane będą umieszczone
            tam dopiero w czasie wywołania metody <methodname>authenticate()</methodname>.
        </para>

        <para>
            Przykładem sytuacji w której można by użyć metody getDbSelect() 
            może być potrzeba sprawdzenia statusu użytkownika, czyli sprawdzenia
            czy konto użytkownika jest aktywne.
        </para>

        <programlisting language="php"><![CDATA[
// Kontynuując poprzedni przykład 
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    'MD5(?)'
);

// pobieramy obiekt Zend_Db_Select (przez referencję)
$select = $adapter->getDbSelect();
$select->where('active = "TRUE"');

// uwierytelniamy, z warunkiem users.active = TRUE
$adapter->authenticate();
]]></programlisting>
    </sect2>
</sect1>