LDAP 認証の場合、認証に一般的に使用されるパラメーターは何ですか。DN を使用すると、ldap 経由でログインするユーザーにとって頭痛の種になると思います。覚えるには大きすぎるためです。私の実装では、対応する uid または sAMAccountName の dn を取得して認証に進む場合、認証にuidまたはsAMAccountNameを使用するオプションはどうですか。
私は正しい道を進んでいますか?
LDAP 認証の場合、認証に一般的に使用されるパラメーターは何ですか。DN を使用すると、ldap 経由でログインするユーザーにとって頭痛の種になると思います。覚えるには大きすぎるためです。私の実装では、対応する uid または sAMAccountName の dn を取得して認証に進む場合、認証にuidまたはsAMAccountNameを使用するオプションはどうですか。
私は正しい道を進んでいますか?
LDAP では、接続またはセッションを認証できます。LDAP クライアントが LDAP ディレクトリ サーバーへの新しい接続を確立すると、接続の認証状態はanonymousになります。LDAP クライアントは、BIND 要求を使用して許可状態の変更を要求できます。
BIND リクエストには、シンプルと SASL の 2 つの形式があります。Simple は識別名とパスワードを使用し、SASL は選択したメカニズムの 1 つを使用します。たとえば、PLAIN、LOGIN、CRAM-MD5、DIGEST-MD5、GSSAPI、および EXTERNAL です。GSSAPI と EXTERNAL を除くすべてのメカニズムは脆弱すぎて使用できません。実稼働シナリオまたはミッション クリティカルな領域で使用します。
単純な BIND を使用するには、BIND 要求を作成し、それを LDAP ディレクトリ サーバーに送信します。LDAP ディレクトリ サーバーは、結果コードを含む BIND 応答で応答します。結果コードは整数で、それ以外のゼロは BIND 要求が失敗したことを示します。結果コードがゼロの場合、BIND 要求は成功し、セッション認証状態は BIND 要求で使用された識別名の状態に変更されています。
同じ接続/セッションでの後続の BIND 要求ごとに、承認状態が匿名に設定され、同じ接続/セッションでの成功した BIND 要求ごとに、承認状態が認証 ID に関連付けられた承認状態に設定されます。単純な BIND の場合は識別名ですが、SASL が使用されている場合はまったく別のものである可能性があります。最新のプロ品質のサーバーは、受信した名前をさまざまな DN にマップできます。
どちらの言語を使用する場合でも、BIND 要求を作成し、それをサーバーに送信して、応答を解釈します。
アップデート:
識別名がわからない場合、または識別名が煩雑な場合 (多くの場合、認証方法を知らず、知っていても構わない Web アプリケーション ユーザーの場合)、LDAP アプリケーションはディレクトリでユーザーを検索する必要があります。成功した検索応答には常に識別名が含まれ、単純な BIND で使用されます。
検索には、少なくとも次のものが含まれます。
dc=example,dc=com
ou=people,dc=example,dc=com
、ベース オブジェクトou=people,dc=example,dc=com
と のスコープを使用しますone-level
。これらの検索パラメーターは、次のようなエントリを検索します。uid=user1,ou=people,dc=example,dc=com
(objectClass=inetOrgPerson)
1.1
。これは、属性がなく、単純な BIND に必要なすべての DN (識別名) で返されることを意味します。ここの概要セクションのリンク
LDAP サーバーは LDAP クエリのみを認識します。あなたや私が慣れているような「ユーザー名」はありません。
LDAP の場合、誰かを認証するには、その人物 (またはエンティティ) の LDAP エントリの識別名を送信する必要があります。パスワードとともに。
sAMAccountNameについて言及したので、Active Directory を使用していると想定しています。Active Directory は匿名バインドを許可します。これは、資格情報を提供せずに接続できることを意味します。ただし、資格情報を提供しないとルックアップを実行できません。
Cythonを使用している場合python-ldap
(このプロセスを非常に簡単にするさまざまな .NET API にアクセスできる IronPython を使用していない場合); 次に、次の手順に従います。
通常、ツリーに対する適切な権限を持つ事前設定されたユーザーを使用し、最初にそのユーザーでディレクトリに接続してから、残りの認証プロセスでそのユーザーのアクセスを使用します。これは一般的に次のようになります。
したがって、次の 2 つの主なものが必要です。
以下は、これを実行できる大まかなコードです。
AD_USER = 'your super user'
AD_PASSWORD = 'your super user password'
AD_BIND_ATTR = 'userPrincipalName' # this is the "login" for AD
AD_URL = "ldap://your-ad-server"
AD_DN = "DC=DOMAIN,DC=COM"
AD_LOGIN_ATTR = 'sAMAccountName' # this is what you user will enter in the form
# as their "login" name,
# this is what they use to login to Windows
# A listing of attributes you want to fetch for the user
AD_ATTR_SEARCH = ['cn',
'userPrincipalName',
'distinguishedName',
'mail',
'telephoneNumber','sAMAccountName']
def _getbinduser(user):
""" This method returns the bind user string for the user"""
user_dn = AD_DN
login_attr = '(%s=%s)' % (AD_LOGIN_ATTR,user)
attr_search = AD_ATTR_SEARCH
conn = ldap.initialize(AD_URL)
conn.set_option(ldap.OPT_REFERRALS,0)
conn.set_option(ldap.OPT_PROTOCOL_VERSION,3)
try:
conn.bind(AD_USER,AD_PASSWORD)
conn.result()
except:
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
# Exit the script and print an error telling what happened.
sys.exit("LDAP Error (Bind Super User)\n ->%s" % exceptionValue)
try:
result = conn.search_s(user_dn,
ldap.SCOPE_SUBTREE,
login_attr, attr_search)
except:
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
# Exit the script and print an error telling what happened.
sys.exit("LDAP Error (Search)\n ->%s" % exceptionValue)
# Return the user's entry from AD, which includes
# their 'distinguished name'
# we use this to authenticate the credentials the
# user has entered in the form
return result[0][1]
def authenticate(user,password):
bind_attr = AD_BIND_ATTR
user_dn = AD_DN
login_attr = '(%s=%s)' % (AD_LOGIN_ATTR,user)
data = _getbinduser(user)
if len(data) == 1:
return None
# Information we want to return from the directory
# for each user, season to taste.
info = {}
info['name'] = data['cn'][0]
info['email'] = data['mail'][0]
try:
info['phone'] = data['telephoneNumber'][0]
except KeyError:
info['phone'] = 'Not Available'
conn = ldap.initialize(Config.AD_URL)
conn.set_option(ldap.OPT_REFERRALS,0)
conn.set_option(ldap.OPT_PROTOCOL_VERSION,3)
try:
# Now we have the "bind attribute" (LDAP username) for our user
# we try and connect to see if LDAP will authenticate
conn.bind(data[bind_attr][0],password)
conn.search(user_dn,ldap.SCOPE_SUBTREE,login_attr,None)
conn.result()
return info
except (ldap.INVALID_CREDENTIALS,ldap.OPERATIONS_ERROR):
return None
テリーの優れたコメントの 1 つの小さな拡張。すべてのユーザーを DIT の同じ部分に格納し、同じ属性を使用してそれらを識別する場合、DN を検索するのではなく、プログラムで DN を構築できます。