Ruby on Rails 3:Devise::LdapAdapter.get_ldap_param 未定义方法错误

2024-04-24

我在跑步: 红宝石 1.9.3p0, 轨道 3.1.1, 设计1.4.9, Devise_ldap_authenticatable 0.4.10

我正在使用 Devise 通过 LDAP 服务器验证我的 Rails 应用程序。我使用用户名而不是电子邮件进行身份验证,因此表中的电子邮件字段自然是空白的。

要查询 ldap 中的电子邮件,官方方法是在用户模型中添加以下代码:

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

和宝石文件:

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 ,用户名是用户中正确的字段名称。该方法有错误吗?会不会是版本不兼容?我不太确定还需要检查什么,并且 Rails 没有给我提供任何适合初学者的东西。我希望得到一些帮助。


我也遇到了这个问题 - 我当前的临时解决方案是自己使用获取数据Net::LDAP而不是ldap_authenticatable类。当然,更永久的解决方案是修补ldap_authenticatable,我接下来可能会尝试这样做。

问题(至少对我来说)是这样的:在仔细研究之后ldap_authenticatable代码(即ldap_adapter.rb)我发现get_ldap_param尝试获取参数时,方法不会与服务器进行身份验证,除非admin_user and admin_password在 ldap.yml 中指定。因此,如果您的 LDAP 服务器允许匿名读取数据,那么get_ldap_param将按照广告宣传的那样工作。在 OpenLDAP(我用于本地测试的)上,匿名读取访问是通过 slapd.conf 中的“access to”属性设置的:

access to *
  by anonymous auth

但是,我的公司 LDAP 不允许这样做。

Net::LDAP 实例位于ldap_authenticatable用于获取参数时需要使用 auth 参数创建,但事实并非如此。没有给出 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

根据您的特定需求进行修改。这并不理想,但目前可以使用,直到分叉/修补为止ldap_authenticatable来解释这个用例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ruby on Rails 3:Devise::LdapAdapter.get_ldap_param 未定义方法错误 的相关文章

随机推荐