2008-12-02 6 views
42

J'ai tenté de connecter une application Rails à ActiveDirectory. Je vais synchroniser les données sur les utilisateurs entre AD et une base de données, actuellement MySQL (mais peut se transformer en SQL Server ou PostgreSQL).LDAP via Ruby ou Rails

J'ai vérifié activedirectory-ruby, et il semble vraiment bogué (pour une version 1.0 !?). Il enveloppe Net :: LDAP, j'ai donc essayé de l'utiliser à la place, mais il est très proche de la syntaxe actuelle de LDAP, et j'ai apprécié l'abstraction de ActiveDirectory-Ruby à cause de sa syntaxe ActiveRecord.

Existe-t-il un outil élégant de type ORM pour un serveur de répertoire? Mieux encore, s'il y avait une sorte d'outil d'échafaudage pour LDAP (CRUD pour les utilisateurs, les groupes, les unités organisationnelles, etc.). Ensuite, je pourrais rapidement l'intégrer avec mon code d'authentification existant via Authlogic, et garder toutes les données synchronisées.

Répondre

38

est un exemple de code Ici, je l'utilise avec la gemme net-ldap pour vérifier les connexions des utilisateurs du serveur ActiveDirectory à mon travail:

require 'net/ldap' # gem install net-ldap 

def name_for_login(email, password) 
    email = email[/\A\w+/].downcase # Throw out the domain, if it was there 
    email << "@mycompany.com"  # I only check people in my company 
    ldap = Net::LDAP.new(
    host: 'ldap.mycompany.com', # Thankfully this is a standard name 
    auth: { method: :simple, email: email, password:password } 
) 
    if ldap.bind 
    # Yay, the login credentials were valid! 
    # Get the user's full name and return it 
    ldap.search(
     base:   "OU=Users,OU=Accounts,DC=mycompany,DC=com", 
     filter:  Net::LDAP::Filter.eq("mail", email), 
     attributes: %w[ displayName ], 
     return_result:true 
    ).first.displayName.first 
    end 
end 

Le code first.displayName.first à la fin semble un peu loufoque, et ainsi pourrait bénéficier de certains explication:

  • Net::LDAP#search renvoie toujours un tableau de résultats, même si vous finissez correspondant à une seule entrée. Le premier appel à first trouve la première entrée (et vraisemblablement seulement) correspondant à l'adresse électronique.

  • Le Net::LDAP::Entry renvoyé par la recherche vous permet d'accéder facilement à des attributs via le nom de méthode, some_entry.displayName est le même que some_entry['displayName'].

  • Chaque attribut d'un Net::LDAP::Entry est toujours un tableau de valeurs, même lorsqu'une seule valeur est présente. Bien qu'il puisse être stupide d'avoir un utilisateur avec plusieurs valeurs "displayName", la nature générique de LDAP signifie que c'est possible. L'appel final first convertit le tableau d'une chaîne en chaîne uniquement pour le nom complet de l'utilisateur.

+0

Merci pour la réponse tardive. Je n'ai plus vraiment besoin de cette information, mais cette syntaxe semble stellaire, et BEAUCOUP plus courte que la façon dont j'essayais de le faire. Merci encore! – Judy

+1

Merci de l'avoir posté. J'avais frappé un mur simplement parce que je n'incluais pas le @ company.com pour le nom d'utilisateur. Votre message m'a fait aller dans la bonne direction. –

1

Avez-vous vérifié ldap-activerecord-gateway de thoughtbot? Il pourrait être quelque chose pour vous d'envisager ...

http://github.com/thoughtbot/ldap-activerecord-gateway/tree/master

+0

Hmm. J'essaie toujours de comprendre ce que cela pourrait faire pour nous. Essentiellement, je voudrais démarrer ce serveur LDAP lors du démarrage de l'application rails. Ensuite, s'il existe un moyen de répliquer les données entre le serveur AD réel et le serveur, faites-le. Ensuite, utilisez mon serveur LDAP pour les données. Est-ce que cela a du sens? – Judy

8
+5

mrT - La plupart des liens qui ont probablement déjà fonctionné dans votre réponse sont maintenant brisés. Pourriez-vous être persuadé de les mettre à jour? Merci d'avance. –

+1

nouveau comment s'authentifier avec ldap lien: http://wiki.rubyonrails.org/rails/pages/howtoauthenticatewithrubynetldap –

4

C'est plus anecdotique que d'une vraie réponse. J'ai eu une expérience similaire en utilisant le serveur Samba et OpenLDAP. Je ne pouvais pas trouver une bibliothèque pour vraiment faire ce que je voulais, donc j'ai roulé mes propres classes d'aide.

J'ai utilisé ldapbrowser pour voir les champs que Samba a remplis lorsque j'ai créé un utilisateur de manière "officielle" et que j'ai dupliqué cela.

La seule chose LDAP délicate/non standard a été le cryptage par mot de passe fou, nous avons:

UserPass:

"{MD5}" + Base64.encode64(Digest::MD5.digest(pass)) 

sambaNTPassword:

OpenSSL::Digest::MD4.hexdigest(Iconv.iconv("UCS-2", "UTF-8", pass).join).upcase 

Pour la fonction def authenticate(user, pass) je tente de obtenir LDAP à lier au domaine en utilisant leurs informations d'identification, si j'attrape une exception, la connexion a échoué, sinon laissez-les.

+0

+1 Merci, je cherchais un moyen de générer un mot de passe nt hash en ruby ​​:) – chmeee

+1

vous avez sauvé quatre vies aujourd'hui. – nurettin

2

J'ai commencé à utiliser ruby-activedirectory, et même étendu/fixé quelques choses, hébergeant judy-activedirectory dans Github. En faisant la prochaine itération, j'ai découvert qu'ActiveLdap avait une bien meilleure base de code, et j'envisage sérieusement d'y passer. Est-ce que quelqu'un a une expérience personnelle avec ça?

+0

+1 pour ruby-activedirectory – chmeee

2

Désolé, il n'y a pas encore de commentaire ... peut-être que quelqu'un peut le déplacer de façon appropriée.

@ solution de Phrogz fonctionne bien, mais bind_simple (à l'intérieur bind) soulève un Net :: LDAP :: exception LdapError en raison de auth [: nom d'utilisateur] ne pas être défini comme indiqué ici:

https://github.com/ruby-ldap/ruby-net-ldap/blob/master/lib/net/ldap.rb

Le corrigées: remplace

auth: { method: :simple, email: email, password:password } 

avec:

auth: { method: :simple, username: email, password:password } 
+0

Incidemment, vous pouvez modifier les messages d'autres personnes - les modifications iront dans la file d'attente des modifications suggérées, où deux personnes peuvent confirmer ou infirmer la modification est une bonne. :) – sarnold