Hi all,
I''ve got a Rails app with a ApplicationController that looks like this:
class ApplicationController < ActionController::Base
before_filter :authorize, :except => :login
def authorize
unless session[:user]
flash[:notice] = "Please log in"
session[:jumpto] = request.parameters
redirect_to :controller => "login", :action =>
"login"
end
end
end
So, basically, redirect a user to the login screen if they haven''t
already
logged in. Pretty standard stuff.
But, if I want to setup a web service, how do I set session data from the
client side through, say, an xmlrpc call using layered dispatching?
I''ve tried
messing around with the block form of the web_service, and even tried setting
up a LoginApi and LoginService, but no luck.
I''d like to be able to do this:
require ''xmlprc/client''
rpc = XMLRPC::Client.new(''localhost'',
''http://localhost/webservice/api'', 3000)
rpc.call(''login.login'', user, password) # Set session data
here
rpc.call(''foo.findFooById'', 2) # Go on my merry way
I googled around a bit and couldn''t quite find the answer I was looking
for.
That, or I''m just not "getting it".
What''s the best/proper way to handle this?
Thanks,
Dan
Hi Daniel,
In my web services I just ignore the authorization, but Im on an
internal app. I think what an app I worked on before ( not rails ) did
was something like:
def ws_auth( user, pword)
# auth the user
# create an entry in the db, and return some sort of unique key
end
def web_service_method( auth_key , ...... )
# if the auth_key doesnt exist in the db, ignore this request
end
then your client does:
auth_key = rpc.call(''login.login'', user, password) # Set
session data
here
rpc.call(''foo.findFooById'',auth_key , 2) # Go on my merry way
not perfect, but might do for you
Paul
Daniel Berger wrote:> Hi all,
>
> I''ve got a Rails app with a ApplicationController that looks like
this:
>
> class ApplicationController < ActionController::Base
> before_filter :authorize, :except => :login
>
> def authorize
> unless session[:user]
> flash[:notice] = "Please log in"
> session[:jumpto] = request.parameters
> redirect_to :controller => "login", :action =>
"login"
> end
> end
> end
>
> So, basically, redirect a user to the login screen if they haven''t
> already
> logged in. Pretty standard stuff.
>
> But, if I want to setup a web service, how do I set session data from
> the
> client side through, say, an xmlrpc call using layered dispatching?
> I''ve tried
> messing around with the block form of the web_service, and even tried
> setting
> up a LoginApi and LoginService, but no luck.
>
> I''d like to be able to do this:
>
> require ''xmlprc/client''
>
> rpc = XMLRPC::Client.new(''localhost'',
''http://localhost/webservice/api'',
> 3000)
> rpc.call(''login.login'', user, password) # Set session
data here
> rpc.call(''foo.findFooById'', 2) # Go on my merry way
>
> I googled around a bit and couldn''t quite find the answer I was
looking
> for.
> That, or I''m just not "getting it".
>
> What''s the best/proper way to handle this?
>
> Thanks,
>
> Dan
--
Posted via http://www.ruby-forum.com/.
Chang Sau Sheong
2006-Apr-22 01:21 UTC
[Rails] web services and dealing with before_filter
What I did was to include in the authorization in the web service. I have a method like User.authenticate?(user) which returns true or false. This is used by my authentication filter as u have done. Every time someone sends in a request they must include the username/password in the request, which is then used to check if he is valid or not. For higher security you can either run it through https (haven''t tried this), encode it in base64, encrypt it using some private key algo, or use WSS4R. This method is probably not high-performing, alternatively you can use a token mechanism to check if he is a valid user (instead of checking everytime, return a token) , but if your requests are low volume it should be ok. Hope this helped. Daniel Berger wrote:> Hi all, > > I''ve got a Rails app with a ApplicationController that looks like this: > > class ApplicationController < ActionController::Base > before_filter :authorize, :except => :login > > def authorize > unless session[:user] > flash[:notice] = "Please log in" > session[:jumpto] = request.parameters > redirect_to :controller => "login", :action => "login" > end > end > end > > So, basically, redirect a user to the login screen if they haven''t > already logged in. Pretty standard stuff. > > But, if I want to setup a web service, how do I set session data from > the client side through, say, an xmlrpc call using layered > dispatching? I''ve tried messing around with the block form of the > web_service, and even tried setting up a LoginApi and LoginService, > but no luck. > > I''d like to be able to do this: > > require ''xmlprc/client'' > > rpc = XMLRPC::Client.new(''localhost'', > ''http://localhost/webservice/api'', 3000) > rpc.call(''login.login'', user, password) # Set session data here > rpc.call(''foo.findFooById'', 2) # Go on my merry way > > I googled around a bit and couldn''t quite find the answer I was > looking for. That, or I''m just not "getting it". > > What''s the best/proper way to handle this? > > Thanks, > > Dan > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Sau Sheong http://blog.saush.com http://read.saush.com http://jaccal.sourceforge.net
You make them supply a user/password *per request*? Ouch. What I would really like is a better way to handle before_filter''s in my controllers within my ActionWebService::Base classes somehow. Maybe there''s a way to accomplish what I want using the block form of the web_service method, but I''m not seeing it. Regards, Dan> -----Original Message----- > From: rails-bounces@lists.rubyonrails.org > [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of > Chang Sau Sheong > Sent: Friday, April 21, 2006 7:22 PM > To: rails@lists.rubyonrails.org > Subject: Re: [Rails] web services and dealing with before_filter > > > What I did was to include in the authorization in the web > service. I have a method like User.authenticate?(user) which > returns true or false. This is used by my authentication > filter as u have done. Every time someone sends in a request > they must include the username/password in the request, which > is then used to check if he is valid or not. > > For higher security you can either run it through https > (haven''t tried this), encode it in base64, encrypt it using > some private key algo, or use WSS4R. > > This method is probably not high-performing, alternatively > you can use a token mechanism to check if he is a valid user > (instead of checking everytime, return a token) , but if your > requests are low volume it should be ok. > > Hope this helped. > > Daniel Berger wrote: > > Hi all, > > > > I''ve got a Rails app with a ApplicationController that looks like > > this: > > > > class ApplicationController < ActionController::Base > > before_filter :authorize, :except => :login > > > > def authorize > > unless session[:user] > > flash[:notice] = "Please log in" > > session[:jumpto] = request.parameters > > redirect_to :controller => "login", :action => "login" > > end > > end > > end > > > > So, basically, redirect a user to the login screen if they haven''t > > already logged in. Pretty standard stuff. > > > > But, if I want to setup a web service, how do I set session > data from > > the client side through, say, an xmlrpc call using layered > > dispatching? I''ve tried messing around with the block form of the > > web_service, and even tried setting up a LoginApi and LoginService, > > but no luck. > > > > I''d like to be able to do this: > > > > require ''xmlprc/client'' > > > > rpc = XMLRPC::Client.new(''localhost'', > > ''http://localhost/webservice/api'', 3000) > rpc.call(''login.login'', user, > > password) # Set session data here > rpc.call(''foo.findFooById'', 2) # Go > > on my merry way > > > > I googled around a bit and couldn''t quite find the answer I was > > looking for. That, or I''m just not "getting it". > > > > What''s the best/proper way to handle this? > > > > Thanks, > > > > Dan > > _______________________________________________ > > Rails mailing list > > Rails@lists.rubyonrails.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > > > -- > Sau Sheong > > http://blog.saush.com > http://read.saush.com > http://jaccal.sourceforge.net > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
Here''s how I ultimately decided to deal with this issue in case
anyone is interested:
1) Created a LoginApi web service. In login_api.rb:
class LoginApi < ActionWebService::API::Base
api_method :login,
:expects => [:string, :string]
end
2) Created a LoginService class. In login_service.rb:
class LoginService < ActionWebService::Base
web_service_api LoginApi
def login(cuid, password)
if User.login(cuid, password)
User.find_by_cuid(cuid)
end
end
end
This assumes a User.login and User.find_by_cuid
method in the User model somewhere. Adjust as needed.
3) Added the appropriate line to the web service controller.
In webservice_controller.rb:
class WebserviceController < ApplicationController
...
web_service :login, LoginService.new
end
4) Within my ApplicationController (application.rb) I
modified my authorize filter like so:
require ''rexml/document''
include REXML
class ApplicationController < ActionController::Base
# User must authorize to get to any screen
before_filter :authorize, :except => :login
model :user
private
def authorize
# If the http path requested is ''/webservice/api'' assume
it''s
# a remote call and give them a chance to login.
if session[:user].nil? &&
request.env[''PATH_INFO''] =''/webservice/api''
doc = Document.new(request.env[''RAW_POST_DATA''])
elements = XPath.match(doc,
"/methodCall/params/param/value/string")
cuid, password = elements.map{ |x| x.text }
session[:user] = LoginService.new.login(cuid, password)
end
unless session[:user]
flash[:notice] = "Please log in"
session[:jumpto] = request.parameters
redirect_to :controller => "login", :action =>
"login"
end
end
end
Adjust the ''/webservice/api'' path as needed.
Sample xmlrpc client:
require ''xmlrpc/client''
rpc = XMLRPC::Client.new(''localhost'',
''http://localhost/webservice/api'',
3000)
rpc.call(''login.Login'', ''user'',
''XXX'') # Only login once
p rpc.call(''hardware.FindHardwareById'', 2)
p rpc.call(''hardware.GetAllHardware'')
This allows the end programmer to login just once within their code,
instead
of having to login on a per-request basis.
I''m not sure how robust or secure this is, so I''m open to
comments and
suggestions.
Regards,
Dan
> -----Original Message-----
> From: rails-bounces@lists.rubyonrails.org
> [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of
> Berger, Daniel
> Sent: Monday, April 24, 2006 12:36 PM
> To: rails@lists.rubyonrails.org
> Subject: RE: [Rails] web services and dealing with before_filter
>
>
> You make them supply a user/password *per request*? Ouch.
>
> What I would really like is a better way to handle
> before_filter''s in my controllers within my
> ActionWebService::Base classes somehow.
>
> Maybe there''s a way to accomplish what I want using the block
> form of the web_service method, but I''m not seeing it.
>
> Regards,
>
> Dan
>
> > -----Original Message-----
> > From: rails-bounces@lists.rubyonrails.org
> > [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of
> > Chang Sau Sheong
> > Sent: Friday, April 21, 2006 7:22 PM
> > To: rails@lists.rubyonrails.org
> > Subject: Re: [Rails] web services and dealing with before_filter
> >
> >
> > What I did was to include in the authorization in the web
> > service. I have a method like User.authenticate?(user) which
> > returns true or false. This is used by my authentication
> > filter as u have done. Every time someone sends in a request
> > they must include the username/password in the request, which
> > is then used to check if he is valid or not.
> >
> > For higher security you can either run it through https
> > (haven''t tried this), encode it in base64, encrypt it using
> > some private key algo, or use WSS4R.
> >
> > This method is probably not high-performing, alternatively
> > you can use a token mechanism to check if he is a valid user
> > (instead of checking everytime, return a token) , but if your
> > requests are low volume it should be ok.
> >
> > Hope this helped.
> >
> > Daniel Berger wrote:
> > > Hi all,
> > >
> > > I''ve got a Rails app with a ApplicationController that
looks like
> > > this:
> > >
> > > class ApplicationController < ActionController::Base
> > > before_filter :authorize, :except => :login
> > >
> > > def authorize
> > > unless session[:user]
> > > flash[:notice] = "Please log in"
> > > session[:jumpto] = request.parameters
> > > redirect_to :controller => "login", :action
=> "login"
> > > end
> > > end
> > > end
> > >
> > > So, basically, redirect a user to the login screen if they
haven''t
> > > already logged in. Pretty standard stuff.
> > >
> > > But, if I want to setup a web service, how do I set session
> > data from
> > > the client side through, say, an xmlrpc call using layered
> > > dispatching? I''ve tried messing around with the block
> form of the
> > > web_service, and even tried setting up a LoginApi and
> LoginService,
> > > but no luck.
> > >
> > > I''d like to be able to do this:
> > >
> > > require ''xmlprc/client''
> > >
> > > rpc = XMLRPC::Client.new(''localhost'',
> > > ''http://localhost/webservice/api'', 3000)
> > rpc.call(''login.login'', user,
> > > password) # Set session data here
> > rpc.call(''foo.findFooById'', 2) # Go
> > > on my merry way
> > >
> > > I googled around a bit and couldn''t quite find the
answer I was
> > > looking for. That, or I''m just not "getting
it".
> > >
> > > What''s the best/proper way to handle this?
> > >
> > > Thanks,
> > >
> > > Dan
> > > _______________________________________________
> > > Rails mailing list
> > > Rails@lists.rubyonrails.org
> > > http://lists.rubyonrails.org/mailman/listinfo/rails
> > >
> >
> >
> > --
> > Sau Sheong
> >
> > http://blog.saush.com
> > http://read.saush.com
> > http://jaccal.sourceforge.net
> >
> > _______________________________________________
> > Rails mailing list
> > Rails@lists.rubyonrails.org
> > http://lists.rubyonrails.org/mailman/listinfo/rails
> >
>
>
> This communication is the property of Qwest and may contain
> confidential or
> privileged information. Unauthorized use of this
> communication is strictly
> prohibited and may be unlawful. If you have received this
> communication
> in error, please immediately notify the sender by reply
> e-mail and destroy
> all copies of the communication and any attachments.
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>
> -----Original Message----- > From: rails-bounces@lists.rubyonrails.org > [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of > Berger, Daniel > Sent: Monday, May 01, 2006 9:58 AM > To: rails@lists.rubyonrails.org > Subject: RE: [Rails] web services and dealing with before_filter > > > Here''s how I ultimately decided to deal with this issue in > case anyone is interested:<snip> Ok, this is odd. The sample Ruby client I provided works fine, i.e. the session data is retained after the call to login.Login. However, this sample Perl client does *not* retain the session data: use strict; use warnings; use Frontier::Client; my $url = "http://localhost:3000/webservice/api"; my $client = Frontier::Client->new(url=>$url) or die $!; $client->call(''login.Login'', ''user'', ''XXX''); print $client->call(''hardware.FindHardwareById'', 2), "\n"; print $client->call(''hardware.GetAllHardware''); Why would session data be retained with the Ruby code but not the Perl code? This is Ruby 1.8.4, Webrick, Windows XP Pro, btw. Regards, Dan This communication is the property of Qwest and may contain confidential or privileged information. Unauthorized use of this communication is strictly prohibited and may be unlawful. If you have received this communication in error, please immediately notify the sender by reply e-mail and destroy all copies of the communication and any attachments.
Ruby''s xmlrpc library knows how to handle cookies. But this functionality is required neither by xmlrpc spec nor by soap spec. For interoperability purposes I''d recommend sending username and password with each request. Kent. On 5/1/06, Berger, Daniel <Daniel.Berger@qwest.com> wrote:> > > -----Original Message----- > > From: rails-bounces@lists.rubyonrails.org > > [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of > > Berger, Daniel > > Sent: Monday, May 01, 2006 9:58 AM > > To: rails@lists.rubyonrails.org > > Subject: RE: [Rails] web services and dealing with before_filter > > > > > > Here''s how I ultimately decided to deal with this issue in > > case anyone is interested: > > <snip> > > Ok, this is odd. The sample Ruby client I provided works fine, i.e. > the session data is retained after the call to login.Login. > > However, this sample Perl client does *not* retain the session data: > > use strict; > use warnings; > use Frontier::Client; > > my $url = "http://localhost:3000/webservice/api"; > my $client = Frontier::Client->new(url=>$url) or die $!; > > $client->call(''login.Login'', ''user'', ''XXX''); > print $client->call(''hardware.FindHardwareById'', 2), "\n"; > print $client->call(''hardware.GetAllHardware''); > > Why would session data be retained with the Ruby code but > not the Perl code? > > This is Ruby 1.8.4, Webrick, Windows XP Pro, btw. > > Regards, > > Dan > > > This communication is the property of Qwest and may contain confidential > or > privileged information. Unauthorized use of this communication is strictly > prohibited and may be unlawful. If you have received this communication > in error, please immediately notify the sender by reply e-mail and destroy > all copies of the communication and any attachments. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Kent --- http://www.datanoise.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060501/df4d49f1/attachment.html
Ah, thanks Kent.
Maybe I''ll tinker with the session storage options instead.
Regards,
Dan
-----Original Message-----
From: rails-bounces@lists.rubyonrails.org
[mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of Kent Sibilev
Sent: Monday, May 01, 2006 10:50 AM
To: rails@lists.rubyonrails.org
Subject: Re: [Rails] web services and dealing with before_filter
Ruby''s xmlrpc library knows how to handle cookies. But this
functionality is required neither by xmlrpc spec nor by soap spec. For
interoperability purposes I''d recommend sending username and password
with each request.
Kent.
On 5/1/06, Berger, Daniel <Daniel.Berger@qwest.com> wrote:
> -----Original Message-----
> From: rails-bounces@lists.rubyonrails.org
> [mailto:rails-bounces@lists.rubyonrails.org ] On
Behalf Of
> Berger, Daniel
> Sent: Monday, May 01, 2006 9:58 AM
> To: rails@lists.rubyonrails.org
> Subject: RE: [Rails] web services and dealing with
before_filter
>
>
> Here''s how I ultimately decided to deal with this
issue in
> case anyone is interested:
<snip>
Ok, this is odd. The sample Ruby client I provided
works fine, i.e.
the session data is retained after the call to
login.Login.
However, this sample Perl client does *not* retain the
session data:
use strict;
use warnings;
use Frontier::Client;
my $url = "http://localhost:3000/webservice/api ";
my $client = Frontier::Client->new(url=>$url) or die $!;
$client->call(''login.Login'', ''user'',
''XXX'');
print $client->call(''hardware.FindHardwareById'', 2),
"\n";
print $client->call('' hardware.GetAllHardware'');
Why would session data be retained with the Ruby code
but
not the Perl code?
This is Ruby 1.8.4, Webrick, Windows XP Pro, btw.
Regards,
Dan
This communication is the property of Qwest and may
contain confidential or
privileged information. Unauthorized use of this
communication is strictly
prohibited and may be unlawful. If you have received
this communication
in error, please immediately notify the sender by reply
e-mail and destroy
all copies of the communication and any attachments.
_______________________________________________
Rails mailing list
Rails@lists.rubyonrails.org
http://lists.rubyonrails.org/mailman/listinfo/rails
--
Kent
---
http://www.datanoise.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://wrath.rubyonrails.org/pipermail/rails/attachments/20060501/89804d5e/attachment.html
Chang Sau Sheong
2006-May-02 23:45 UTC
[Rails] web services and dealing with before_filter
It sounds a bit extreme, yes, but it''s not too intrusive actually. I store the username/password before anything happens and then use it to access the web service. The user doesn''t have to repeatedly enter data. Berger, Daniel wrote:> You make them supply a user/password *per request*? Ouch. > > What I would really like is a better way to handle before_filter''s > in my controllers within my ActionWebService::Base classes somehow. > > Maybe there''s a way to accomplish what I want using the block form > of the web_service method, but I''m not seeing it. > > Regards, > > Dan > > >> -----Original Message----- >> From: rails-bounces@lists.rubyonrails.org >> [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of >> Chang Sau Sheong >> Sent: Friday, April 21, 2006 7:22 PM >> To: rails@lists.rubyonrails.org >> Subject: Re: [Rails] web services and dealing with before_filter >> >> >> What I did was to include in the authorization in the web >> service. I have a method like User.authenticate?(user) which >> returns true or false. This is used by my authentication >> filter as u have done. Every time someone sends in a request >> they must include the username/password in the request, which >> is then used to check if he is valid or not. >> >> For higher security you can either run it through https >> (haven''t tried this), encode it in base64, encrypt it using >> some private key algo, or use WSS4R. >> >> This method is probably not high-performing, alternatively >> you can use a token mechanism to check if he is a valid user >> (instead of checking everytime, return a token) , but if your >> requests are low volume it should be ok. >> >> Hope this helped. >> >> Daniel Berger wrote: >> >>> Hi all, >>> >>> I''ve got a Rails app with a ApplicationController that looks like >>> this: >>> >>> class ApplicationController < ActionController::Base >>> before_filter :authorize, :except => :login >>> >>> def authorize >>> unless session[:user] >>> flash[:notice] = "Please log in" >>> session[:jumpto] = request.parameters >>> redirect_to :controller => "login", :action => "login" >>> end >>> end >>> end >>> >>> So, basically, redirect a user to the login screen if they haven''t >>> already logged in. Pretty standard stuff. >>> >>> But, if I want to setup a web service, how do I set session >>> >> data from >> >>> the client side through, say, an xmlrpc call using layered >>> dispatching? I''ve tried messing around with the block form of the >>> web_service, and even tried setting up a LoginApi and LoginService, >>> but no luck. >>> >>> I''d like to be able to do this: >>> >>> require ''xmlprc/client'' >>> >>> rpc = XMLRPC::Client.new(''localhost'', >>> ''http://localhost/webservice/api'', 3000) >>> >> rpc.call(''login.login'', user, >> >>> password) # Set session data here >>> >> rpc.call(''foo.findFooById'', 2) # Go >> >>> on my merry way >>> >>> I googled around a bit and couldn''t quite find the answer I was >>> looking for. That, or I''m just not "getting it". >>> >>> What''s the best/proper way to handle this? >>> >>> Thanks, >>> >>> Dan >>> _______________________________________________ >>> Rails mailing list >>> Rails@lists.rubyonrails.org >>> http://lists.rubyonrails.org/mailman/listinfo/rails >>> >>> >> -- >> Sau Sheong >> >> http://blog.saush.com >> http://read.saush.com >> http://jaccal.sourceforge.net >> >> _______________________________________________ >> Rails mailing list >> Rails@lists.rubyonrails.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> >> > > > This communication is the property of Qwest and may contain confidential or > privileged information. Unauthorized use of this communication is strictly > prohibited and may be unlawful. If you have received this communication > in error, please immediately notify the sender by reply e-mail and destroy > all copies of the communication and any attachments. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails > >-- Sau Sheong http://blog.saush.com http://www.projectible.com http://jaccal.sourceforge.net -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060502/8b9d41ea/attachment.html