我正在运行: ruby 1.9.3p0, rails 3.1.1, 设计 1.4.9, Devise_ldap_authenticatable 0.4.10
我正在使用 Devise 通过 ldap 服务器验证我的 Rails 应用程序。我使用用户名而不是电子邮件进行身份验证,所以我表中的电子邮件字段自然是空白的。
在ldap中查询email,官方的做法是在用户模型中加入这段代码:
before_save :get_ldap_email
def get_ldap_email
self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail")
end
这段代码失败了,没有尝试对 ldap 做任何事情:
undefined method `mail' for nil:NilClass
指的是方法定义里面的那一行。日志输出不再有用:
Started POST "/users/sign_in" for 10.50.1.96 at 2011-11-15 11:18:16 -0800
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"<hidden>=", "user"=>{"username"=>"<hidden>", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."username" = '<hidden>' LIMIT 1
LDAP: LDAP dn lookup: uid=<hidden>
LDAP: LDAP search for login: uid=<hidden>
LDAP: Authorizing user <hidden>
LDAP: LDAP dn lookup: uid=<hidden>
LDAP: LDAP search for login: <hidden>
Completed 500 Internal Server Error in 251ms
NoMethodError (undefined method `mail' for nil:NilClass):
app/models/user.rb:14:in `get_ldap_email'
500 错误之前的所有行都是正常的 LDAP 成功验证,与电子邮件查询无关。
我上周才开始学习 Ruby、Rails 和 Devise,所以我不确定哪些文件最能说明问题,但这是我的 user.rb 模型和 gemfile:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :ldap_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_save :get_ldap_email
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :username, :password, :password_confirmation, :remember_me
def get_ldap_email
self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail")
end
end
还有 gemfile:
source 'http://rubygems.org'
gem 'rails', '3.1.1'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
<... unrelated ...>
gem 'therubyracer', :platforms => :ruby
gem "devise"
gem "devise_ldap_authenticatable"
我已尝试重新启动服务器,并在上次 GemFile 更新后完成了捆绑安装。我的配置有 ldap_create_user = true 并且 username 是用户中的正确字段名称。那个方法有错误吗?会不会是版本不兼容?我不太确定还有什么要检查的,而且 Rails 没有给我任何适合初学者的东西。我希望得到一些帮助。
最佳答案
我也有这个问题 - 我目前的临时解决方案是使用 Net::LDAP
而不是 ldap_authenticatable
类自己获取数据。当然,更永久的解决方案是修补 ldap_authenticatable
,我接下来可能会尝试这样做。
问题(至少对我而言)是这样的:在仔细研究了 ldap_authenticatable
代码(即 ldap_adapter.rb)后,我发现 get_ldap_param
方法未通过身份验证服务器在尝试获取参数时,除非在 ldap.yml 中指定了 admin_user
和 admin_password
。因此,如果您的 LDAP 服务器允许匿名读取数据,则 get_ldap_param
将如宣传的那样工作。在 OpenLDAP(这是我用于本地测试的)上,匿名读取访问是使用 slapd.conf 中的“访问”属性设置的:
access to *
by anonymous auth
但是,我的公司 LDAP 不允许这样做。
ldap_authenticatable
中的Net::LDAP 实例在用于取参时需要使用auth 参数创建,但事实并非如此。未提供身份验证参数,因此不会返回任何结果。
所以,暂时,我的用户模型中有以下代码,调用 get_ldap_data
作为 before_save 过滤器:
def has_ldap_data?
[self.email, self.first_name, self.last_name].none? {|v| v.nil?}
end
def get_ldap_data
return true if has_ldap_data? or self.password.nil?
ldap = create_ldap
ldap.search(
:base => ldap.base,
:attributes => ['cn', 'sn', 'givenname', 'mail'],
:filter => Net::LDAP::Filter.eq('cn', self.username),
:return_result => true) do |entry|
self.email = entry.mail.first
self.first_name = entry.givenname.first
self.last_name = entry.sn.first
end
has_ldap_data?
end
def create_ldap(password = nil)
ldap_config = ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
ldap_options = {
:host => ldap_config["host"],
:port => ldap_config["port"],
:base => ldap_config["base"],
:auth => {
:method => :simple,
:username => "cn=#{self.username},#{ldap_config['base']}",
:password => password || self.password
}
}
ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true
ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"]
Net::LDAP.new(ldap_options)
end
根据您的特定需求进行修改。这并不理想,但目前可以使用,直到 fork /修补 ldap_authenticatable
以解决此用例。
关于ruby-on-rails - Ruby on Rails 3: Devise::LdapAdapter.get_ldap_param 未定义方法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8142587/