I haven't found a good answer to this yet. How can I get my Rails app and Sinatra app (mounted in my Rails app's config.ru) to share a session successfully? If I visit my Sinatra app first, then the Rails app, I get an error like undefined method sweep for {}:Hash, presumably because Rails uses a custom subclass of Hash for storing session info, and Rack::Session::Cookie doesn't. My code so far:
config.ru
map "/" do
run MyRailsApp::Application
end
map "/sinatra" do
use Rack::Session::Cookie,
key: "_app_session",
secret: "<SECRET_KEY>"
run MySinatraApp
end
config/initializers/session_store.rb
MyRailsApp::Application.config.session_store :cookie_store, key: '_app_session'
config/initializers/secret_token.rb
MyRailsApp::Application.config.secret_token = "<SECRET_KEY>" # same as config.ru
Anything I've missed?
A quick grep of the Rails source reveals sweep is a method on ActionDispatch::Flash::FlashHash, which Rails stores in the session under the flash key.
Sinatra-Flash also uses the flash key of the session, but it stores a plain Hash object there.
Rails is getting the object at session['flash'], which is the Hash put there by Sinatra, assuming it is a FlashHash and trying to call sweep on it, hence the error message: undefined method sweep for {}:Hash.
A possible work around might be to use a different key in the Sinatra app for the flash rather than the default (e.g. flash(:my_flash)[:error]="foo").
That won't help if you want to use the flash to see messages when going between Rails and Sinatra though.
The "undefined method sweep for {}:Hash" issue is with your browser storing previously cached cookies. Just delete the cookies related to the application and refresh the browser. It worked for me.
Related
I've got a Rails 2.3.5 application that I'm migrating to Rails 3.0.10 that's run into a problem with sessions.
Some code is failing during integration tests because the session has no id (request.session is an empty hash, and request.session_options[:id] is nil). We are currently using webrat, but the same thing happens with capybara and with standard rails helpers. Sessions do seem to be set up properly, since some of the integration tests have session ids. It looks like the session id is missing only in tests that don't log in before trying to access the session id (i.e. most of them).
I've tried switching the session backend (it's currently cookie based) to ActiveRecord, but that didn't help. I've created a new Rails 3.0.10 app, and it also has nil session ids. I've even dug into Rails's session handling, and it looks like there's no session id being generated on if a session is missing one.
Is this lack of session ids expected behavior that's documented somewhere? If it's a bug, is there a version of Rails that generates session ids properly?
The only way I've seen how to solve this is to prime the sessions.
sid1 = session[:session_id]
sid2 = request.session_options[:id]
However, if for some reason the session cookie is deleted, it can still happen.
I tried that and no result. I also tried session[:foo] = 'bar' as I liked the way it looked better but still no result.
I rebooted and still no joy. Then I went into my browser settings and deleted my cookies. That fixed it. From this experience it appears a cookie can keep sessions from being forced. I had been changing class names and changing my database tables. Somehow I had corrupted my cookie.
I am trying to integrate twitter into devise using this guide. I basically take all occurence of facebook and substitue it with twitter. However, when I sign in with twitter, I am getting the following error:
ActionDispatch::Cookies::CookieOverflow (ActionDispatch::Cookies::CookieOverflow):
at the following url:
http://localhost:3000/users/auth/twitter/callback?oauth_token=something&oauth_verifier=blah
Is there any nice way to get around fixing this problem?
Thanks!
The problem is with session["devise.facebook_data"] = env["omniauth.auth"]. Twitter's response contains an extra section that is very large and does not fit in the session. One option is to store env["omniauth.auth"].except("extra") in the session instead.
You can turn on ActiveRecord store for session.
Look in config/initializers/session_store.rb
comment out the line about using :cookie_store
uncomment the lines at the bottom about using :active_record_store
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rails generate session_migration")
MyApp::Application.config.session_store :active_record_store
Create migration before rails rails g session_migration and migrate it.
I have a project that uses Sinatra for static pages and Rails for the application.
I allow the request to hit one or the other by doing this in config.ru:
run Rack::Cascade.new([
EightyEightTactical::Root,
EightyEightTactical::Application
])
Where EightyEightTactical::Root is a subclass of Sinatra::Base and EightyEightTactical::Application is a subclass of Rails::Application.
I'm in a tricky situation where I need to set a flash message in a Rails controller and display it in a Sinatra layout.
I notice that Rails uses ActionDispatch::Flash in middleware, but I can't seem to figure out how to access the flash messages outside of a Rails app. Am I mistaken, or can this be done?
Assuming you are using a Cookie session store, you can do the following:
1) Access the session cookie with the name specified in config/initializers/session_store.rb.
2) Decrypt the session cookie to get the session hash
3) Access the key called flash which contains a hash.
4) Iterate and display the flash message.
You should look at ActionController::Session::CookieStore class for more details.
I'd like my users to be able to use Google Translate with my Rails apps. I have forms and login for the app. I keep getting the Rails InvalidAuthenticityToken when using the app through Google Translate.
Any insights on how i can get both to work? I am using Rails 2.5.x.
Thank you!
PS: To clarify, this the authenticity token works fine without going through Google Translate. I suspect it's something to do with the domain?
This is a feature of rails that prevents cross site scripting attacks. It really depends what you are doing but what you need to do is pass this secret that rails passes in every params hash. Check you log file or server or debug your params and you will see this. It is a really long code.
This code is generate in your environment.rb file so whenever you pass params to your application you need to include this file.
Anyone have any "best practices" tips for Rails and sessions? The default session type for Rails 3 is still CookieStore, right? I used SqlSessionStore for a while and it worked well, but I may move away from that in favor of CookieStore.
Is it still not a good idea to use CookieStore for sensitive info, even with salted info or is that better stored in the DB?
Use the database for sessions instead of the cookie-based default, which shouldn't be used to store highly confidential information
Create the session table with
rake db:sessions:create
Run the migration
rake db:migrate
Make sure you also tell rails to use ActiveRecord to manage your sessions too.
Rails 3
config/initializers/session_store.rb:
Rails.application.config.session_store :active_record_store
Rails 2
config/environment.rb:
config.action_controller.session_store = :active_record_store
Cookies are encrypted by default in Rails 4
In Rails 4, CookieStore cookies are encrypted and signed by default:
If you only have secret_token set, your cookies will be signed, but not
encrypted. This means a user cannot alter their user_id without knowing your
app's secret key, but can easily read their user_id. This was the default
for Rails 3 apps.
If you have secret_key_base set, your cookies will be encrypted. This goes a
step further than signed cookies in that encrypted cookies cannot be altered
or read by users. This is the default starting in Rails 4.
If you have both secret_token and secret_key_base set, your cookies will
be encrypted, and signed cookies generated by Rails 3 will be transparently
read and encrypted to provide a smooth upgrade path.
Active Record Session Store is Deprecated in Rails 4
This answer is now out-of-date with regard to Rails 4. The Active Record
Session Store has been deprecated and removed from Rails, so the following
generators will no longer work:
rake db:sessions:create
rails generate session_migration
This was pointed out in this answer. The reason that the Active Record
Session Store was deprecated is because the reads/writes to the database don't
scale well when you have a large number of users accessing your application, as
stated in this blog post:
...one major issue with the Active Record session store is that it is not
scalable. It puts an unnecessary load on your database. Once your application
receives a large amount of traffic, the sessions database table is
continuously bombarded with read/write operations.
As of Rails 4, the Active Record session store has be removed from the core
framework and is now deprecated.
If you still want to use the Active Record Session Store, it's still available
as a gem.
Current Rails Session Best Practices
For more current best practices for Ruby on Rails sessions, I advise that you
check out the lastest versions of the Ruby on Rails Security Guide.
I don't believe anything has changed in how anyone on any platform should handle cookie based sessions. Be skeptical of anything that passes beyond the server's control (cookies, form posts, etc.) Thats a general principle of web development.
As far the encryption, I don't know if anything has changed on that front.
Something to be mindful of with a cookie store is the limit to the amount of data, and the gotcha that this data will be sent on the wire in every request, where as a database store only transfers the id and the data lives on the server.
FWIW, rails 3.1 suggests running
rails generate session_migration
However this generates the exact same migration as
rake db:sessions:create
The Rails defaults seem pretty good to me- The CookieStore is fast and should cover the majority of use cases. Sure you're limited to 4kb and your data will be visible to the user, but the Rails way is to only use session for things like integer IDs and basic string values- If you're trying to store objects or highly confidential information in session you're probably doing it wrong.