Read cookie

  • Thread starter PÃ¥l Bergström
  • Start date
B

Brian Candler

Pål Bergström said:
But that's in the controller. Or do I miss something?

Yes, it's in the controller.
One more time:

1) I have a Rails app.

2) I have/had certain data aes encrypted in certain columns in mysql
with a unique key for each user. That key is saved in a cookie. If they
use an iPhone or another browser they need to ad the key to each
browser. It's just another layer of security on top of Rails. So if
someone get hold of that key it's useless unless you login or break the
security of mysql.

3) l use "before_save" and "fast-aes" in the model. So everything happes
in the model and in a script for encrypting located in /lib, just
because I can't get the cookie into the model with rails
cookies[:my_cookie]. Or can I? Maybe I'm overlooking something. Can get
the value of a cookie from the controller into the model in a simple
uniform way?

Ah right, so now you're definitely asking a Rails question. I think your
question is: how can I access request/controller parameters from an
instance of the model?

The brief answer is: you can't. An instance of a model exists
independently of any controller. A model can be instantiated outside of
a controller; and in principle, one model object could be shared between
multiple controller instances.

A simple solution is to pass the parameter explicitly. That is, in your
model you can have a method which accepts the encryption key as a
parameter, like 'decrypt' say, and invoke it from the controller:

# code in controller
...
thing = Thing.find(id)
thing.decrypt(cookies["key"])
...

Or you could set an instance variable in the model (models can have
regular Ruby attrs, which are not stored in the database), which in turn
you can use in your before_save method.

If you want to make it completely transparent, there is a messy solution
you could consider, which is to use Thread-local variables. In your
controller's "before" filter, do

Thread[:key] = cookies["key"]

Then this will be accessible in your model as Thread[:key]. You need to
be very careful to reset this variable before *every* controller action,
otherwise the key may leak from one user's request to another user.

This is actually how Rails deals with timezones - in the controller, if
you set Time.zone = xxx in the controller, it affects the model through
a thread-local variable. See

http://api.rubyonrails.org/classes/Time.html#method-c-zone=

and click on "show source".

I'd recommend you avoid doing this if you possibly can. I think in your
case, I'd use an instance variable.

class MyModel < ActiveRecord::Base
attr_accessor :key

def before_save
raise "Key not set!" unless key
... encrypt using key
end
end

class MyController < ApplicationController
def create
@thing = MyModel.new(params[:thing])
@thing.key = cookies[:key]
@thing.save!
end
end

Of course, you do need to update your code at each point where you load
or save models, but there is no risk of one user's key hanging over to
another request.

This of course a 100% Rails question. If you didn't get a good answer on
a Rails forum, maybe you needed to be bit clearer in the phrasing of
your question. There is good advice at
http://www.catb.org/~esr/faqs/smart-questions.html#intro

In future I'd recommend you be more specific about what you're trying to
do; post samples of code; and mark the points where you're having
problems. One ambiguous sentence just doesn't cut it, and most people
are likely to skip over it.

HTH,

Brian.
 
P

Pål Bergström

Brian said:
In future I'd recommend you be more specific about what you're trying to
do; post samples of code; and mark the points where you're having
problems. One ambiguous sentence just doesn't cut it, and most people
are likely to skip over it.


Thanks for your time and effort to answer. I appreciate it. I have given
detailed explanation for what I wanted to do several times (before
this). So I thought I would just ask: Can Ruby access a cookie in a
users browser? I could do it with cgi but not anymore.

I know I can pass it to the model with a params. But that means sending
it on many occasions instead of setting it once. Maybe you have given me
a solution to that with Thread-local variables. I will examine your
answer more closely.

I don't have the before_save and after_find in the controller. It's in
the model.
 
B

Brian Candler

Pål Bergström said:
So I thought I would just ask: Can Ruby access a cookie in a
users browser?

And I say again, that question is completely meaningless. Ruby is a
programming language; it can do anything that a programming language can
do. But by itself it knows nothing about cookies - they are an artefact
of HTTP. So you need to be talking about a Ruby HTTP environment, such
as Rails or Sinatra or Rack or Webrick, which deals with incoming HTTP
requests. That's the "context" which someone else asked for.

All of these do have mechanisms for accessing cookies - even if it's
only directly accessing the HTTP Cookie: and Set-Cookie: headers - so
the answer to your question is quite clearly "Yes".

However, I imagine that "Yes" is not the answer you were looking for.

What you actually have is a problem, and you want help finding a
solution. In that case, you need to describe the specific problem.

"I cannot access cookies in Rails" is not sufficient - clearly you can,
and I showed you code which does it.

"in Rails, I cannot access cookies inside a model object" is getting
there. Or "I know how to access cookies inside the Rails controller but
not in other objects"

Even if you wrote some code in lib/foo.rb, this is still running in the
context some Ruby HTTP framework; how you access cookies depends on what
the framework provides. If it were running standalone it wouldn't
receive a HTTP request in the first place (unless you were writing a
HTTP server from scratch)
I could do it with cgi but not anymore.

That also means nothing unless you expand on "it" (what you're trying to
do), or the problem (you have some code which worked before but which
does not work now, in which case you can post the code itself and ask
for ways to rewrite it)

In the very old days, I think Rails had a global CGI object for "the
current request", since it was only ever intended to handle one request
at a time within any particular process. Now that Rails apps can be
multi-threaded, this will have been removed, as it wouldn't make any
sense - each controller instance must have its own HTTP request object.
They've also removed the use of the CGI library, since Rack does it
better and faster.
I don't have the before_save and after_find in the controller. It's in
the model.

Yes, it's part of the design of Rails that models have before_save and
after_find hooks. Note that ActiveRecord, from which you have built your
models, is also a part of Rails - albeit one which can be used outside
of Rails quite easily.

Regards,

Brian.
 
P

Pål Bergström

Brian said:
you need to describe the specific problem.

I know. I believe I did that. As I said I've asked before, not this
time. But there is a reason for that. I think the problem is our
different mindsets. I don't know, so I ask stupid questions. You know
and don't really understand my problem and what I'm trying to do as my
question is unlogical.

Thank you for the clarification. I'll guess I will use the instance
variable and add it everywhere I need it. I was hoping I could avoid
that.
 
J

Josh Cheek

2010/9/4 P=E5l Bergstr=F6m said:
Thank you for the clarification. I'll guess I will use the instance
variable and add it everywhere I need it. I was hoping I could avoid
that.
You could put it in a method in your ApplicationController, then in each of
your specific controllers, just use a before filter to apply it to the
methods you want. Then you only have to have one additional line in each of
the controllers that will use that before filter.


class ApplicationController < ActionController::Base
def verify_key
redirect_to some_path unless logged_in? &&
current_user.valid_key?(session['aes-key'])
end
end

class ResourcesTypeOneController < ApplicationController
before_filter :verify_key , :eek:nly =3D> [:destroy, :edit , :update]
# ...
end

class ResourcesTypeTwoController < ApplicationController
before_filter :verify_key , :except =3D> [:show]
# ...
end
 
P

Pål Bergström

Jesús Gabriel y Galán said:
That should read Enumerable#find

If you understand what I'm trying to do, do you think the use of
Mechanize is a good or bad idea? Is it better to use the instance
variable to send the variable from controller to the model?

(As you said, probably more a Rails question. But now I'm here :) )
 
B

Brian Candler

If you understand what I'm trying to do, do you think the use of=20
Mechanize is a good or bad idea? Is it better to use the instance=20
variable to send the variable from controller to the model?

Mechanize is a HTTP *client* - a programmable web browser if you like.

Rails is a HTTP *server*.

You wouldn't use Mechanize in a Rails app, unless your Rails app was in t=
urn
connecting to a different web server and pulling information from that.

If you connected to your own web server using Mechanize, the web server
would see it as a new client, distinct from all your other clients, and
probably generate a new cookie for it.
 
J

Jesús Gabriel y Galán

2010/9/6 P=E5l Bergstr=F6m said:
If you understand what I'm trying to do, do you think the use of
Mechanize is a good or bad idea? Is it better to use the instance
variable to send the variable from controller to the model?

(As you said, probably more a Rails question. But now I'm here :) )

I answered what I did in case you were really looking after calling a
website and retrieving the cookie from the response. It seems that I
misunderstood your question, since it's obvious from the following
conversation that you were talking about retrieving the cookie from a
client's request. I don't know much about Rails, Brian and others have
given advice regarding that.

Now that your question is clear (reading a cookie from the request and
using it around controllers and models) you won't need Mechanize for
anything.

Jesus.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,372
Latest member
LucretiaFo

Latest Threads

Top