Active Directory(以降AD)サーバにldap関数を使って接続するときには,いくつか注意すべき点があります。
uidではなくsAMAccountNameを使う
認証(authentication)の研究(1)で紹介したpsychicの記事にあるfindAll関数では$attribute引数の初期値に'uid'という値が使われています。。Linux+OpenLDAPで運用されているLDAPサーバーの場合は,アカウント名を示す属性はuidなのですが,ADのLDAPディレクトリの場合にはこの属性はありません。ADで同様な意味を持つ属性は,sAMAccountNameです。cnが使えそうに思うかもしれませんが,これは使えません。ADのサーバー上でウィザードを使ってユーザーを新規作成した場合には,cnには姓名がセットされてしまうからです。相手がADサーバーの場合はsAMAccountNameを使います。
パスワードが空だとldap_bindはtrueを返す
次に,これはちょっとハマったのですが,ldap_bind関数でADに接続するとき,パスワードが空欄の場合はldap_bindは一応成功してしまうという点に注意が必要です。そんな場合はldap_bindの戻り値にtrueが返ってきますが,それ以降のldapに対する処理ldap_searchなどは失敗します。ldap_bindを使ってユーザー名とパスワードの組み合わせが正しいかどうか認証をする場合には,ldap_bindで認証する前に空のパスワードの場合をはじいておかなければいけません。
AD認証の手順
ADは匿名bindを許しませんので,認証手順としては次のようになります。
- ユーザー名とパスワードをチェックしていずれかが空欄の場合は認証失敗とします。
- bind用のユーザー名とパスワードでADにbindします。ldap_bind
- ADのsAMAccount属性を検索して与えられたユーザー名があるかどうか調べます。ldap_search
- あった場合は,そのアカウントのdnを調べます。ldap_search, ldap_first_entry, ldap_getdn
- dnとパスワードでldapにバインドしてみます。ldap_bind
これらの処理が通れば,ADにより認証されたということになります。
基本的な疑問
ここまでの実験をいろいろやっていまして,一つ疑問に思うことがあります。CakePHPではcore.phpで定義されているDEBUG定数の値,画面へのデバッグ情報の表示を制御していますが,ldap_bindで認証処理を行うと,認証できなかった場合にかならずエラーが表示されてしまうので,うまく認証できなかった場合の動作確認がちゃんとできないんですよね。DEBUG定数に優先するようなエラー処理を書くことってできないのでしょうか。これって基本的なことで,とても恥ずかしい諮問かもしれません。