Zend_Ldap.xml 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15742 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.ldap.using">
  5. <title>Einleitung</title>
  6. <note>
  7. <title>Minimale Funktionalität</title>
  8. <para>
  9. Im Moment ist diese Klasse nur dafür gedacht, die beschränkte Funktionalität zu bieten,
  10. die für <link
  11. linkend="zend.auth.adapter.ldap"><classname>Zend_Auth_Adapter_Ldap</classname></link>
  12. nötig ist. Weiterführende Verwendungsmöglichkeiten wie das Suchen, Erstellen,
  13. Bearbeiten oder Umbenennen von Objekten im Verzeichnis werden im Moment nicht
  14. unterstützt und werden zu einem späteren Zeitpunkt hinzugefügt werden.
  15. </para>
  16. </note>
  17. <para>
  18. <classname>Zend_Ldap</classname> ist eine Klasse, mit der LDAP-Operationen, wie das
  19. Durchsuchen, das Bearbeiten oder die Bindung an Einträge im LDAP-Verzeichnis, durchgeführt
  20. werden können.
  21. </para>
  22. <sect2 id="zend.ldap.using.theory-of-operation">
  23. <title>Beschreibung</title>
  24. <para>
  25. Diese Komponente besteht im Moment aus zwei Klassen, <classname>Zend_Ldap</classname>
  26. und <classname>Zend_Ldap_Exception</classname>. Ein
  27. <classname>Zend_Ldap</classname>-Objekt repräsentiert konzeptionell die Bindung an einen
  28. einzelnen LDAP server. Die Parameter für diese Bindung können explizit oder in der form
  29. eines Optionen-Arrays angegeben werden.
  30. </para>
  31. <para>
  32. Die Verwendung von <classname>Zend_Ldap</classname> hängt von der Art Ihres LDAP-Servers
  33. ab und kann am besten mit einigen einfachen Beispielen erklärt werden.
  34. </para>
  35. <para>
  36. Wenn Sie OpenLDAP benutzen, wäre ein einfaches Beispiel das Folgende (Beachten Sie:
  37. Die Option <code>bindRequiresDn</code> ist wichtig, wenn Sie <emphasis>nicht</emphasis>
  38. Microsoft Active Directory benutzen):
  39. <programlisting language="php"><![CDATA[
  40. $options = array(
  41. 'host' => 's0.foo.net',
  42. 'username' => 'CN=user1,DC=foo,DC=net',
  43. 'password' => 'pass1',
  44. 'bindRequiresDn' => true,
  45. 'accountDomainName' => 'foo.net',
  46. 'baseDn' => 'OU=Sales,DC=foo,DC=net',
  47. );
  48. $ldap = new Zend_Ldap($options);
  49. $acctname = $ldap->getCanonicalAccountName('abaker',
  50. Zend_Ldap::ACCTNAME_FORM_DN);
  51. echo "$acctname\n";
  52. ]]></programlisting>
  53. </para>
  54. <para>
  55. Wenn Sie Microsoft Active Directory nutzen, sollte das folgende Beispiel funktionieren:
  56. <programlisting language="php"><![CDATA[
  57. $options = array(
  58. 'host' => 'dc1.w.net',
  59. 'useStartTls' => true,
  60. 'username' => 'user1@w.net',
  61. 'password' => 'pass1',
  62. 'accountDomainName' => 'w.net',
  63. 'accountDomainNameShort' => 'W',
  64. 'baseDn' => 'CN=Users,DC=w,DC=net',
  65. );
  66. $ldap = new Zend_Ldap($options);
  67. $acctname = $ldap->getCanonicalAccountName('bcarter',
  68. Zend_Ldap::ACCTNAME_FORM_DN);
  69. echo "$acctname\n";
  70. ]]></programlisting>
  71. Beachten Sie, dass wir die Methode <code>getCanonicalAccountName()</code> hier nur
  72. benutzen, um den Domain-Name des Accounts 'bcarter' zu erhalten, weil das so ziemlich
  73. alles von dem wenigen Code, der im Moment in dieser Klasse vorhanden ist, verwendet.
  74. </para>
  75. <sect3 id="zend.ldap.using.theory-of-operation.username-canonicalization-automatic">
  76. <title>Automatische Normalisierung des Benutzernamens bei der Server-Bindung</title>
  77. <para>
  78. Wenn <code>bind()</code> mit einem nicht-DN-konformen Benutzernamen aufgerufen wird
  79. aber <code>bindRequiresDN</code> <constant>TRUE</constant> ist und kein Benutzername in
  80. DN-Form als Option angegeben wird, wird die Server-Bindung fehlschlagen. Wenn
  81. allerdings ein Benutzername in DN-Form im Optionen-Array übergeben wurde, wird
  82. <classname>Zend_Ldap</classname> sich zuerst mit diesem Benutzernamen an den Server
  83. binden, den Account-Domain Name für den Benutzernamen, der <code>bind()</code>
  84. suchen und sich dann neu mit diesem DN verbinden.
  85. </para>
  86. <para>
  87. Dieses Verhalten ist wichtig für <classname>Zend_Auth_Adapter_Ldap</classname>, das
  88. den eingegebenen Benutzernamen direkt an <code>bind()</code> weiterleitet.
  89. </para>
  90. <para>
  91. Das folgende Beispiel zeigt, wie der nicht DN-konforme Benutzername
  92. '<code>abaker</code>' mit <code>bind()</code> benutzt werden kann:
  93. <programlisting language="php"><![CDATA[
  94. $options = array(
  95. 'host' => 's0.foo.net',
  96. 'username' => 'CN=user1,DC=foo,DC=net',
  97. 'password' => 'pass1',
  98. 'bindRequiresDn' => true,
  99. 'accountDomainName' => 'foo.net',
  100. 'baseDn' => 'OU=Sales,DC=foo,DC=net',
  101. );
  102. $ldap = new Zend_Ldap($options);
  103. $ldap->bind('abaker', 'moonbike55');
  104. $acctname = $ldap->getCanonicalAccountName('abaker',
  105. Zend_Ldap::ACCTNAME_FORM_DN);
  106. echo "$acctname\n";
  107. ]]></programlisting>
  108. Der Aufruf von <code>bind()</code> in diesem Beispiel erkennt dass der Benutzername
  109. '<code>abaker</code>' nicht in DN-Form ist und dass <code>bindRequiresDn</code>
  110. <constant>TRUE</constant> ist, verwendet '<code>CN=user1,DC=foo,DC=net</code>' und
  111. '<code>pass1</code>' zum Verbinden, empfängt den DN für '<code>abaker</code>',
  112. löst die Bindung und bindet sich dann neu mit dem jetzt bekannten
  113. '<code>CN=Alice Baker,OU=Sales,DC=foo,DC=net</code>'.
  114. </para>
  115. </sect3>
  116. <sect3 id="zend.ldap.using.theory-of-operation.options">
  117. <title>Zend_Ldap Optionen</title>
  118. <para>
  119. Die <classname>Zend_Ldap</classname>-Komponente akzeptiert ein Array von Optionen,
  120. das entweder im Konstruktor oder der Methode <code>setOptions()</code> übergeben
  121. werden kann. Folgende Optionen sind möglich:
  122. <table id="zend.ldap.using.theory-of-operation.options.table">
  123. <title>Zend_Ldap Optionen</title>
  124. <tgroup cols="2">
  125. <thead>
  126. <row>
  127. <entry>Name</entry>
  128. <entry>Beschreibung</entry>
  129. </row>
  130. </thead>
  131. <tbody>
  132. <row>
  133. <entry>host</entry>
  134. <entry>
  135. Host-Name des LDAP-Servers, wenn er nicht in <code>connect()</code>
  136. überschrieben wird. (kann auch verwendet werden, wenn die Komponente
  137. versucht, Benutzernamen in <code>bind()</code> zu normalisieren).
  138. </entry>
  139. </row>
  140. <row>
  141. <entry>port</entry>
  142. <entry>
  143. Port des LDAP-Servers, wenn er nicht in <code>connect()</code>
  144. überschrieben wird.
  145. </entry>
  146. </row>
  147. <row>
  148. <entry>useStartTls</entry>
  149. <entry>
  150. Ob der LDAP-Client TLS (auch SSL-v2) verschlüsselte Übertragung
  151. verwenden soll. Der Wert <constant>TRUE</constant> ist auf jeden Fall in
  152. Produktivumgebungen empfohlen, damit Passwörter nicht im Klartext
  153. übertragen werden. Der Standardwert ist <constant>FALSE</constant>, weil Server
  154. fast immer verlangen, dass ein Verschlüsselungszertifikat
  155. nachinstalliert wird.
  156. </entry>
  157. </row>
  158. <row>
  159. <entry>useSsl</entry>
  160. <entry>
  161. Ob der LDAP Client SSL verschüsselte Übertragung unterstützen sollten
  162. oder nicht. Die <code>useSsl</code> und <code>useStartTls</code>
  163. Optionen sind gegenseitig exklusiv.
  164. </entry>
  165. </row>
  166. <row>
  167. <entry>username</entry>
  168. <entry>
  169. Der Standard-Benutzername. Bei manchen Servern muss dieser in DN-Form
  170. vorliegen.
  171. </entry>
  172. </row>
  173. <row>
  174. <entry>password</entry>
  175. <entry>
  176. Das Passwort des Standard-Benutzernamens.
  177. </entry>
  178. </row>
  179. <row>
  180. <entry>bindRequiresDn</entry>
  181. <entry>
  182. Wenn dieser Wert<constant>TRUE</constant> ist, wird
  183. <classname>Zend_Ldap</classname> den Domain-Name für den Account, der
  184. zur Bindung genutzt wird, suchen, wenn der Benutzername noch nicht in
  185. DN-Form ist. Der Standardwert ist <constant>FALSE</constant>.
  186. </entry>
  187. </row>
  188. <row>
  189. <entry>baseDn</entry>
  190. <entry>
  191. Der Standard-DN, unter dem gesucht wird (bspw. Accounts). Diese Option
  192. wird für die meisten Account-Bezogenen Vorgänge benötigt und sollte
  193. den DN beinhalten, unter dem die Accounts liegen.
  194. </entry>
  195. </row>
  196. <row>
  197. <entry>accountCanonicalForm</entry>
  198. <entry>
  199. Eine Integerzahl, die die Art angibt, in der Account-Namen normalisiert
  200. werden. Schauen Sie für mehr Informationen in die Tabelle
  201. <emphasis>Accountnamen-Normalisierung</emphasis> weiter unten.
  202. </entry>
  203. </row>
  204. <row>
  205. <entry>accountDomainName</entry>
  206. <entry>
  207. Der vollqualifizierte Domain-Name, für den der LDAP-Server eine
  208. Autorität ist.
  209. </entry>
  210. </row>
  211. <row>
  212. <entry>accountDomainNameShort</entry>
  213. <entry>
  214. Der 'Kurz'-Domain-Name für den der LDAP-Server eine Autorität ist.
  215. Wird normalerweise in Windows-Netzwerken genutzt, um NetBIOS-Namen zu
  216. definieren, kann aber auch von Nicht-AD-Servern genutzt werden.
  217. </entry>
  218. </row>
  219. <row>
  220. <entry>accountFilterFormat</entry>
  221. <entry>
  222. Der LDAP-Suchfilter, der verwendet wird, um Accounts zu suchen. Dieser
  223. String ist ein Ausdruck im Stil von <ulink
  224. url="http://php.net/printf"><code>printf()</code></ulink>,
  225. der ein '<code>%s</code>' enthalten muss, das durch den Benutzernamen
  226. ersetzt wird. Der Standardwert ist
  227. '<code>(&amp;(objectClass=user)(sAMAccountName=%s))</code>', es sei denn
  228. <code>bindRequiresDn</code> ist <constant>TRUE</constant>. In diesem Fall ist
  229. der Standardwert
  230. '<code>(&amp;(objectClass=posixAccount)(uid=%s))</code>'.
  231. Wenn eigene Schemata benutzt werden, muss diese Option vielleicht
  232. geändert werden.
  233. </entry>
  234. </row>
  235. <row>
  236. <entry>allowEmptyPassword</entry>
  237. <entry>
  238. Einige LDAP Server können so konfiguriert werden das Sie ein leeres
  239. Passwort als anonyme Bindung akzeptieren. Dieses Verhalten ist fast
  240. immer unerwünscht. Aus diesem Grund sind leere Passwörter explizit nicht
  241. erlaubt. Wenn dieser Wert auf <constant>TRUE</constant> gesetzt wird ist die
  242. Übermittlung eines leeres Passwortes wärend des Bindens erlaubt.
  243. </entry>
  244. </row>
  245. <row>
  246. <entry>optReferrals</entry>
  247. <entry>
  248. Auf <constant>TRUE</constant> gesetzt, zeigt diese Option dem LDAP Client das
  249. Referenzen gefolgt werden soll. Der Standardwert ist <constant>FALSE</constant>.
  250. </entry>
  251. </row>
  252. </tbody>
  253. </tgroup>
  254. </table>
  255. </para>
  256. </sect3>
  257. <sect3 id="zend.ldap.using.theory-of-operation.account-name-canonicalization">
  258. <title>Normalisierung von Accountnamen</title>
  259. <para>
  260. Die Optionen <code>accountDomainName</code> and <code>accountDomainNameShort</code>
  261. werden für zwei Zwecke genutzt: Erstens bieten sie Mehrdomain-Authentifizierung und
  262. Möglichkeiten zur Ausfallsicherung, und zweitens werden sie benutzt, um
  263. Benutzernamen zu normalisieren, nach der Vorgabe der Option
  264. <code>accountCanonicalForm</code>. Diese Option kann einen der folgenden Werte
  265. annehmen:
  266. <table id="zend.ldap.using.theory-of-operation.account-name-canonicalization.table">
  267. <title>accountCanonicalForm</title>
  268. <tgroup cols="3">
  269. <thead>
  270. <row>
  271. <entry>Name</entry>
  272. <entry>Wert</entry>
  273. <entry>Beispiel</entry>
  274. </row>
  275. </thead>
  276. <tbody>
  277. <row>
  278. <entry><code>ACCTNAME_FORM_DN</code></entry>
  279. <entry>1</entry>
  280. <entry>CN=Alice Baker,CN=Users,DC=example,DC=com</entry>
  281. </row>
  282. <row>
  283. <entry><code>ACCTNAME_FORM_USERNAME</code></entry>
  284. <entry>2</entry>
  285. <entry>abaker</entry>
  286. </row>
  287. <row>
  288. <entry><code>ACCTNAME_FORM_BACKSLASH</code></entry>
  289. <entry>3</entry>
  290. <entry>EXAMPLE\abaker</entry>
  291. </row>
  292. <row>
  293. <entry><code>ACCTNAME_FORM_PRINCIPAL</code></entry>
  294. <entry>4</entry>
  295. <entry>abaker@example.com</entry>
  296. </row>
  297. </tbody>
  298. </tgroup>
  299. </table>
  300. </para>
  301. <para>
  302. Die standardmäßige Normalisierung hängt davon am, welche Optionen zum Account-DN
  303. übergeben wurden. Wenn <code>accountDomainNameShort</code> angegeben wurde, ist
  304. der Standardwert von <code>accountCanonicalForm</code>
  305. <code>ACCTNAME_FORM_BACKSLASH</code>. Wenn dagegen <code>accountDomainName</code>
  306. angegeben wurde, ist der Standardwert <code>ACCTNAME_FORM_PRINCIPAL</code>.
  307. </para>
  308. <para>
  309. Die Normalisierung von Account-Namen stellt sicher, dass der String, der zur
  310. Identifizierung eines Accounts verwendet wird, einheitlich ist, egal was
  311. an <code>bind()</code> übergeben wurde. Wenn der Benutzer bspw.
  312. <emphasis>abaker@example.com</emphasis> oder einfach <emphasis>abaker</emphasis>
  313. als Benutzernamen angibt und <code>accountCanonicalForm</code> auf 3 gesetzt ist,
  314. wird der normalisierte Name <emphasis>EXAMPLE\abaker</emphasis> sein.
  315. </para>
  316. </sect3>
  317. <sect3 id="zend.ldap.using.theory-of-operation.multi-domain-failover">
  318. <title>Authentifizierung auf mehreren Domains und Ausfallsicherung</title>
  319. <para>
  320. <classname>Zend_Ldap</classname> an sich wird nicht versuchen, sich mit mehreren
  321. Servern zu verbinden. Allerdings ist <classname>Zend_Ldap</classname> auf dieses
  322. Szenario vorbereitet. Dazu können Sie einfach ein Array mit Optionen für mehrere
  323. Server durchlaufen und nacheinander versuchen, sich mit jedem Server zu verbinden.
  324. Wie oben beschrieben wird <code>bind()</code> automatisch jeden Benutzernamen
  325. normalisieren, also ist es egal, ob der Benutzer <code>abaker@foo.net</code> oder
  326. <code>W\bcarter</code> oder <code>cdavis</code> als Benutzernamen angibt -
  327. <code>bind()</code> wird fehlschlagen, wenn der Login nicht erfolgreich war.
  328. </para>
  329. <para>
  330. Das folgende Beispiel zeigt Authentifizierung auf mehreren Domains und eine
  331. Ausfallsicherung.
  332. <programlisting language="php"><![CDATA[
  333. $acctname = 'W\\user2';
  334. $password = 'pass2';
  335. $multiOptions = array(
  336. 'server1' => array(
  337. 'host' => 's0.foo.net',
  338. 'username' => 'CN=user1,DC=foo,DC=net',
  339. 'password' => 'pass1',
  340. 'bindRequiresDn' => true,
  341. 'accountDomainName' => 'foo.net',
  342. 'accountDomainNameShort' => 'FOO',
  343. 'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
  344. 'baseDn' => 'OU=Sales,DC=foo,DC=net',
  345. ),
  346. 'server2' => array(
  347. 'host' => 'dc1.w.net',
  348. 'useSsl' => true,
  349. 'username' => 'user1@w.net',
  350. 'password' => 'pass1',
  351. 'accountDomainName' => 'w.net',
  352. 'accountDomainNameShort' => 'W',
  353. 'accountCanonicalForm' => 4, // ACCT_FORM_PRINCIPAL
  354. 'baseDn' => 'CN=Users,DC=w,DC=net',
  355. ),
  356. );
  357. $ldap = new Zend_Ldap();
  358. foreach ($multiOptions as $name => $options) {
  359. echo "Versuche, mit den Server-Optionen für '$name' zu verbinden\n";
  360. $ldap->setOptions($options);
  361. try {
  362. $ldap->bind($acctname, $password);
  363. $acctname = $ldap->getCanonicalAccountName($acctname);
  364. echo "AUSGEFÜHRT: $acctname angemeldet\n";
  365. return;
  366. } catch (Zend_Ldap_Exception $zle) {
  367. echo ' ' . $zle->getMessage() . "\n";
  368. if ($zle->getCode() === Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) {
  369. continue;
  370. }
  371. }
  372. }
  373. ]]></programlisting>
  374. Wenn die Bindung an einen Server aus irgendeinem Grund fehlschlägt, wird sie
  375. mit dem nächsten Server erneut versucht.
  376. </para>
  377. <para>
  378. Der Aufruf von <code>getCanonicalAccountName</code> gibt den normalisierten
  379. Account-Namen zurück, den die Anwendung vermutlich benutzen würde, um Daten - wie
  380. bspw. Einstellungen - damit zu assoziieren. Die Option
  381. <code>accountCanonicalForm = 4</code>, die in diesem Fall in den Optionen aller
  382. Server gesetzt ist, stellt sicher, dass die normalisierte Form in einem
  383. einheitlichen Format ist, egal welcher Server am Ende benutzt wurde.
  384. </para>
  385. <para>
  386. Die besondere Ausnahme <code>LDAP_X_DOMAIN_MISMATCH</code> tritt auf, wenn ein
  387. Account-Name angegeben wurde, der einen Domain-Teil beinhaltet (bspw.
  388. <code>abaker@foo.net</code> oder <code>FOO\abaker</code> und nicht nur
  389. <code>abaker</code>), aber dieser Domain-Teil mit keiner Domain in den aktuell
  390. ausgewählten Server-Optionen übereinstimmt. Diese Ausnahme zeigt an, dass der
  391. Server keine Autorität für diesen Account ist. In diesem Fall wird eine Bindung
  392. nicht ausgeführt, um unnötige Server-Anfragen zu vermeiden. Beachten Sie, dass
  393. die Anweisung <code>continue</code> in diesem Beispiel keine Auswirkung hat, aber
  394. Sie werden im praktischen Einsatz zur Fehlerbehandlung und aus Debugging-Gründen
  395. wahrscheinlich neben <code>LDAP_X_DOMAIN_MISMATCH</code> auch noch auf die
  396. Exception-Codes <code>LDAP_NO_SUCH_OBJECT</code> und
  397. <code>LDAP_INVALID_CREDENTIALS</code> prüfen wollen.
  398. </para>
  399. <para>
  400. Der obige Code ist dem sehr ähnlich, der in <link
  401. linkend="zend.auth.adapter.ldap"><classname>Zend_Auth_Adapter_Ldap</classname></link>
  402. verwendet wird. Wir empfehlen daher, einfach den Authentifizierungs-Adapter
  403. für Multi-Domain-Authentifizierung und LDAP-basierte Authentifizierung mit
  404. Ausfallsicherung zu verwenden (oder kopieren Sie den Code oben).
  405. </para>
  406. </sect3>
  407. </sect2>
  408. </sect1>
  409. <!--
  410. vim:se ts=4 sw=4 et:
  411. -->