.NET で LDAP認証する

#.NET で LDAP 認証にはまった際の備忘録。
##はじめに
十何年かぶりにプログラムを書けと言われて渡されたのが、.NET で LDAP認証をするというものでした。
ググれば出てくるだろうと思ったら、やはり出てきました。
`System.DirectoryServices.DirectoryEntry` を使っているサンプルがほとんどだったのですが、やってみるとうまく動かず･･･
何の LDAPサーバが使用されているか開示されなかったせいもあると思うのですけど･･･
##System.DirectoryServices.Protocols.LdapConnection を使う
.NET Framework をいろいろ漁ってみたら、便利そうなのがありました。
`System.DirectoryServices.Protocols.LdapConnection` です！
##環境
| Software         |Version            |
|:-----------------|:------------------|
| VisualStudio     |2017　　　          |
| .NET Framework   |4.X　　            |
##実装
###VBの場合
今回は VB.NET 実装しました。

```vb
'参照にも追加しないとダメです。
Imports System.DirectoryServices.Protocols
Imports System.Net

'変数
Dim lc As LdapConnection = Nothing
Dim userid As String = "12345"          '検索したいユーザID
Dim ls As String = "192.168.1.1"        'LDAP Server
Dim lsp As String = "389"               'LDAP Server 検索ポート番号
Dim lu As String = "cn=ldapAdmin,c=JP"  'LDAP 管理ユーザ
Dim lp As String = "pwd"                'LDAP 管理ユーザパスワード
Dim ld As String = "ou=users,c=JP"      'LDAP 検索DN

'実装
Try
    lc = New LdapConnection(ls + ":" + lsp)
    lc.Credential = New NetworkCredential(lu, lp)
    lc.AuthType = AuthType.Basic
    lc.SessionOptions.ProtocolVersion = 3
    lc.Timeout = New TimeSpan(0, 0, 60)
    lc.Bind()

    Dim sr As SearchRequest = New SearchRequest
    sr.DistinguishedName = ld
    sr.Filter = String.Format("uid={0}", userid)
    Dim lr As SearchResponse = lc.SendRequest(sr)

    For Each se As SearchResultEntry In lr.Entries
        For Each a As DictionaryEntry In se.Attributes

            Console.WriteLine("Attributes: " + a.Key.ToString + ": " + a.Value.item(0).ToString)
           'Attributes には、以下のような属性が格納されていました。
           '"uid"           'ユーザID
           '"password"      'パスワード
           '"sn"            '氏名
           '"displayName"   '表示名
           '"givenName"     '名前
           '"initials"      'イニシャル
           '"description"   '説明
           '"mail"          'メール
           '"company"       '会社名
           '"department"    '所属
        Next
    Next

Catch ex As Exception
    '例外
    'LdapConnection の例外は、LdapException
Finally
    lc.Dispose()
End Try
```

### C＃の場合
多分、こんな感じだと思います。

```csharp
//参照にも追加しないとダメです。
using System.DirectoryServices.Protocols;
using System.Net;

//変数
LdapConnection lc = null;
string userid = "12345";         //検索したいユーザID
String ls = "192.168.1.1";       //LDAP Server
String lsp = "389";              //LDAP Server 検索ポート番号
string lu = "cn=ldapAdmin,c=JP"; //LDAP 管理ユーザ
string lp = "pwd";               //LDAP 管理ユーザパスワード
string ld = "ou=users,c=JP";     //LDAP 検索DN

//実装
try
{
	lc = new LdapConnection(ls + ":" + lsp);
	lc.Credential = new NetworkCredential(lu, lp);
	lc.AuthType = AuthType.Basic;
	lc.SessionOptions.ProtocolVersion = 3;
	lc.Timeout = new TimeSpan(0, 0, 60);
	lc.Bind();
	SearchRequest sr = new SearchRequest();
	sr.DistinguishedName = ld;
	sr.Filter = string.Format("uid={0}", userid);
	IEnumerator enumerator = ((SearchResponse)lc.SendRequest(sr)).Entries.GetEnumerator();
	if (enumerator.MoveNext())
	{
		//((SearchResultEntry)enumerator.Current).Attributes
		//とかで、Attributes を取ってくる。
	}
}
catch (Exception e)
{
	//例外
}
finally
{
	IDisposable disposable = enumerator as IDisposable;
	if (disposable != null)
	{
		disposable.Dispose();
	}
}
```
#できた

#感想
疲れました･･･
今回はLDAP 管理ユーザ を使えとのことだったので使ったのですが、本当に使ってもよかったのかが疑問に残ります。