Zend_Ldap.xml 21 KB

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