I was moving a application for network management in Rails into a production environment.
It had originally started out as something for my own use.
Of course I did not do security for a single user app.
In previous apps I'd used authenticated system with ldap to give a sign-on.
I wanted easier and tighter integration. NTLM comes to mind, as you can just clink a link,
and your windows login is re-used for your web application.
The problem has always been that mongrel does not support NTLM.
Well that solved now. Thanks to the work of Seggy Umboh, there is a new
NTLM filter for mongrel.
http://github.com/secobarbital/mongrel-ntlm/tree/master
This actually passes you the windows domain user name
directly into your controller.
To get mongrel to use the filter, you must pass a config file, as
documented in the readme.
Then you need a few things in your app:
First in your routes:
map.connect 'ntlm/login', :controller => 'account', :action => 'login'
I added this so the ntlm mongrel filter will chain to my account controller. That way
your "user" controller can remain unchanged. I just prefer to keep them separate.
Easier to add into existing systems that way.
The in the account controller you need the following:
class AccountController < ApplicationController
layout 'tier1'
def login
my_user_name = request.env['REMOTE_USER']
if my_user_name.nil?
session[:logged_in] = :false
return
end
myuser = User.find(:first, :conditions => ["name = ?", my_user_name])
if myuser.nil?
myuser = User.new
myuser.name = my_user_name
myuser.save
end
session[:current_user] = my_user_name
session[:user_id] = myuser.id
session[:logged_in] = :true
redirect_back_or_default('/myapp')
end
end
Then you need a little helper lib. This one is cut down from authenticated system.
This should be in you lib directory.
#ntlm_system.rb
module NtlmSystem
protected
# Returns true or false if the user is logged in.
# Preloads @current_user with the user model if they're logged in.
def logged_in?
if session[:logged_in].nil?
return false
end
if session[:logged_in] == :false
return false
end
return true
end
def login_required
if logged_in?()
return
end
pp "Access Denied"
access_denied()
end
# Redirect as appropriate when an access request fails.
# Our application only uses ntlm based login - you must be part of the domain
def access_denied
redirect_to('/ntlm/login')
end
# Store the URI of the current request in the session.
#
# We can return to this location by calling #redirect_back_or_default.
def store_location
session[:return_to] = request.request_uri
end
# Redirect to the URI stored by the most recent store_location call or
# to the passed default.
def redirect_back_or_default(default)
session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
session[:return_to] = nil
end
end
Finally in your application.rb
# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
include NtlmSystem # Add this for NTLM to work
# See ActionController::RequestForgeryProtection for details
# Uncomment the :secret if you're not using the cookie session store
protect_from_forgery :secret => '6e2f000403020a0d9041a7bfb069239d'
# See ActionController::Base for details
# Uncomment this to filter the contents of submitted sensitive data parameters
# from your application log (in this case, all fields with names like "password").
filter_parameter_logging :password
end
When you start your application, make sure you do it like this:
mongrel_rails start -S config\mongrel_ntlm.conf
After reading, on NTLM, and playing with it, I found the URL are a bit picky, if you
want to use the app, without needing to key your username and password
http://servername:3000/ work perfectly fine.
If you put the whole name, it tends to ask you the user name and password
2 comments:
I wonder if they're using rubysspi behind the scenes.
http://rubyforge.org/projects/rubysspi/
I solved the same issue by using Apache and mod_ntlm and this solution could be installed on Linux and Mac OS X as well.
I saw that mongrel_ntlm requires 'win32/sspi'. Does it mean that it could be used only on Windows?
Post a Comment