Para hacer una pruebas he necesitado autenticar contra un servidor LDAP con Rails, pero la verdad que tras buscar y buscar no he encontrado mucha información. Entre las cosas que he encontrado ha sido el plugin Ruby/ActiveLdap (http://www.activeldap.com/).
¿Qué es ActiveLdap?
“Ruby/ActiveLdap provides an object oriented interface to LDAP. This library was inspired by ActiveRecord (both the concept and the library). It maps LDAP entries to Ruby objects with LDAP attribute accessors exposed as methods dynamically assigned based on your LDAP schema and each object’s objectClasses.”
Es en esta página (www.activeldap.com) dónde podemos encontrar 2 minitutoriales interesantes:
- Installing Ruby/ActiveLdap on Ubuntu Dapper 6.06 LTS or Feisty 7.04
- A Sample Application with ActiveLDAP
Con estas librería podemos conectar con un árbol, realizar consultas… pero no son en sí un sistema de autenticación, sino que hemos de implementarlo nosotros mismos. Para mis pruebas me he decantado por utilizar el sistema explicado en ‘Practical Rails Social Networking Sites (Expert’s Voice)’, aunque modificado para que autentique contra un árbol. Tengo claro que no es ni mucho menos el mejor sistema del mundo, pero bueno… para mis pruebas me sirve. Pienso que lo correcto sería modificar acts_as_authenticated y modificarlo para que funcione con este plugin.
lib/authenticate_ldap_system:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
module AuthenticateLdapSystem protected def is_logged_in? @logged_in_user = LdapUser.find(:all,:attribute => 'uid', :value => session[:user]) if session[:user] end def logged_in_user return @logged_in_user if is_logged_in? end def logged_in_user=(user) if !user.nil? session[:user] = user.uid @logged_in_user = user end end def self.included(base) base.send :helper_method, :is_logged_in?, :logged_in_user end def login_required unless is_logged_in? flash[:error] = 'Debe estar autenticado para realizar esta acción.' redirect_to :controller => 'account', :action => 'login' end end end |
controllers/application.rb:
1 2 3 4 5 6 7 8 9 10 |
class ApplicationController < secret =""> 'd3ae1ee162786bf4a3ad4fbcabdb4019' # Hacemos que las contraseñas no salgan en claro en los logs filter_parameter_logging "password" # Incluimos nuestro sistema de autenticación include AuthenticateLdapSystem end |
controllers/login_controller.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class LoginController < logged_in_user =" LdapUser.authenticate(params[:user][:username]," action =""> 'login' end end def logout if request.post? reset_session flash[:notice] = 'Acaba de dejar la zona segura.' end redirect_to index_url end end |
model/ldap_user.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class LdapUser < dn_attribute =""> "uid", :prefix => "ou=Usuarios", :classes => ['top'], :scope => :one belongs_to :blog, :class => 'Blog', :foreign_key => 'uid' def self.authenticate(username, password) ActiveLdap::Base.establish_connection( :host => "ldap.ejemplo.com", :port => 389, :base => "dc=ejemplo", :bind_dn => "uid=#{username},ou=usuarios,dc=ejemplo", :password_block => Proc.new { password }, :allow_anonymous => false) LdapUser.find(:first,:attribute => 'uid', :value => username) rescue ActiveLdap::AuthenticationError return null end |
