LDAP認証の検証時にパケットキャプチャしてみてどんなことが行われているか調べてたのでついでに載せておく。
LDAP認証時にはアプリケーションとLDAPサーバは以下のやり取りをおこなう。
- ユーザの認証(ユーザ名+パスワード)
- ユーザ情報の取得
- 所有する権限の取得
具体的には以下のようなLDAPのやり取りが発生する。
ユーザの認証
- bindRequestをLDAPサーバへ送信する
- name:認証対象のユーザDN(uid=xxx)
- password:平文送信
- LDAPサーバからbindResponseが返る
- 認証OK:success
- 認証NG:invalidCredentials
ユーザ情報の取得
- serchRequestをLDAPサーバへ送信する
- baseObject:ユーザDN(uid=xxx)
- scope:baseObject
- LDAPサーバからserchResEntryが返る
- ユーザDNが持つobjectClassと属性が返る
- sn
- cn
- uid
- userPassword: 登録時の値(SSHAで返る)
- LDAPサーバからserchResDoneが返る。
- unbindRequestをLDAPサーバへ送信して通信終了
所有する権限の取得
- bindRequestをLDAPサーバへ送信する
- name:なし(Root)
- password:なし
- ※SpringSecurtyの設定で管理者DNとパスワードを設定していればそれで接続
- LDAPサーバからbindResponseが返る
- uniqueMemberが一致する情報を問い合わせるためserchRequestをLDAPサーバへ送信する
- baseObject:権限情報の格納先DN(ou=role,dc=test,dc=example,jc=jp)
- scope:singleLevel
- filter:uniqueMember value:ユーザDN(uid=xxx)
- LDAPサーバからserchResEntryが返る
- 問い合わせ結果が一致する個数分の応答結果が返る
- uid=gokuuの場合はadminとuserの2件が返る
- LDAPサーバからserchResDoneが返る。
- 通信は終了せず接続を維持する
- 他のユーザの所有する権限の取得はbindRequestを実行しない
上記を図にすると以下のような流れになる。
ユーザ認証とその後のユーザ情報の取得ではその都度コネクションを作成するが、権限情報の取得ではコネクションの作成自体は一度だけのようだ。
LDAP自体は暗号化がないため認証時のパスワードは普通に平文で流れている。またパスワードも属性の一つなので応答結果としても返る。登録時は暗号化すべきだろう。