Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
863 views
in Technique[技术] by (71.8m points)

ruby on rails - Devise ignoring custom strategy

This is just plain weird.

I've got Rails 3 RC running with Devise installed. I've defined a custom strategy to try and use Kerberos for authentication.

module Devise
  module Strategies
    class Kerb < Devise::Strategies::Base
      def valid?
        params[:username] || params[:password]
      end

      def authenticate!
        # cheap debugging
        puts "PARAMS: #{params}"

        if check_kerb_auth(params[:username], params[:password])
          # create user account if none exists
          u = User.find(:first, :conditions => { :username => params[:username] }) || User.create({ :username => login })
          success!(u)
        else
          fail!("Could not log in")
        end
      end

      def check_kerb_auth(username, password)
        require 'krb5_auth'
        include Krb5Auth

        return false if username.blank? or password.blank?

        begin
            kerberos = Krb5.new
            return kerberos.get_init_creds_password(username, password)
        rescue Krb5Auth::Krb5::Exception
            return false
        end
      end
    end
  end
end

I have the Devise Warden configuration setup as follows:

config.warden do |manager|
  manager.strategies.add(:kerb, Devise::Strategies::Kerb)
  manager.default_strategies :kerb
end

I get no errors in my log. Everything seems to work ok. If I add "cheap debugging" aka a bunch of puts statements, it seems to reflect that the :kerb strategy is the default. Here is a sample set of logs from a login attempt:

=> Booting WEBrick
=> Rails 3.0.0.rc application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-08-17 10:50:35] INFO  WEBrick 1.3.1
[2010-08-17 10:50:35] INFO  ruby 1.8.7 (2010-01-10) [x86_64-linux]
[2010-08-17 10:50:40] INFO  WEBrick::HTTPServer#start: pid=12717 port=3000


Started POST "/users/login" for 127.0.0.1 at Tue Aug 17 10:50:43 -0400 2010
  Processing by Devise::SessionsController#create as HTML
  Parameters: {"commit"=>"Login", "authenticity_token"=>"afZF6ho96p47dc9LQFwwNN5PqnRpl7x+1J7V3MiKgTE=", "_snowman"=>"342230203", "user"=>{"remember_me"=>"1", "username"=>"hernan43", "password"=>"[FILTERED]"}}
Completed   in 0ms
  Processing by Devise::SessionsController#new as HTML
  Parameters: {"commit"=>"Login", "authenticity_token"=>"afZF6ho96p47dc9LQFwwNN5PqnRpl7x+1J7V3MiKgTE=", "_snowman"=>"342230203", "user"=>{"remember_me"=>"1", "username"=>"hernan43", "password"=>"[FILTERED]"}}
Rendered devise/shared/_links.erb (1.2ms)
Rendered devise/sessions/new.html.erb within layouts/application (8.2ms)
Completed 200 OK in 124ms (Views: 11.7ms | ActiveRecord: 1.3ms)

The kerberos code works in other things on the same machine. I was sort of expecting it to show a bunch of errors if there was a problem but I am getting nothing. Is there a good way to debug Devise/Warden?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In case someone else comes across this, here's what I believe the problem is:

According to Warden Strategies:

valid?

The valid? method acts as a guard for the strategy. It’s optional to declare a valid? method, and if you don’t declare it, the strategy will always be run. If you do declare it though, the strategy will only be tried if #valid? evaluates to true.

The strategy above is reasoning that if there’s either a ‘username’ or a ‘password’ param, then the user is trying to login. If there’s only one of them, then the ‘User.authenticate’ call will fail, but it was still the desired (valid) strategy.

So your valid method:

def valid?
  params[:username] || params[:password]
end

It's returning false, so the authenticate! is never called. params is a nested hash, so it should be params[:user][:username] instead of params[:username].

Changing your valid method to:

def valid?
  params[:user] && (params[:user][:username] || params[:user][:password])
end

will return true and cause the authenticate! method to be called.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...