Zend_Ldap.xml 21 KB

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