skip to main |
skip to sidebar
- Do you need protection_forgery? Yes!
- Does a browser need cookies turned on? Yes!
- Is there no otherway around it? No!
Passing infomation in the url is neiter restful, nor safe!
- What about people that have their cookies turned off?
We have to give let them know that cookies are safe in the contect of our application, and they hold no personal information and they are encrypted.
- What about mobile phone browsers that mostly have no cookie capabilities?
Same as cookies turned off, may adding somthing about mobile phones too.
OR
The user can set up his account as "Mobile Phone Enabled" from a web browser and tell them about the cookie problem, but give them the solution to have the application use IP as the cooke key - with the small problem that if thier provider issues them with a new IP during the session, they will have to relogin.
In some cases, you might really really want to know it the visiting browser has thier cookies on or off. One reason that I an think off is that you are using some ajax stuff on your the landing page that lets unregistered users edit a list or somthing.
This is a way of doing it.
1. Check to see if a cookie has been set for the session,
2. if not then check to see if this ip is in the middle of cookie detection
3. if not then redirect to a method and check again - if no cookies are on now, then be sure they are off.
Now you can either ask them to put them on to gain full functionallity of the application, or let the application blend out functions that cause UPDATE, PUT or DESTROY requests and instead show a flash error message that informs them of the reduced functionality.
This means that you will force a redirect on each request for browsers that have thier cookies off.
In the application.rb add the following:
before_filter :cookies_required, :except => [:check_for_cookies]
protected
def cookies_on?
..!request.cookies["_yourapp_session"].to_s.blank?
end
def cookies_required
..return unless request.cookies["_yourapp_session"].to_s.blank?
..if DetectCookie.find_and_destroy_or_create_by_remote_ip(request.remote_ip, request.request_uri) then return end
..session[:return_to] = request.request_uri
..redirect_to detect_cookies_path
end
>ruby script/generate model DetectCookie remote_ip:string request_uri:string
>rake db:migrate
Create a controller: dectect_cookies.rb
add the following:
class DetectCookiesController < ApplicationController
..before_filter :cookies_required, :except => :show
..def show
....if request.cookies["_hausursel_session"].to_s.blank? #change to your cookie session name
......detect_cookie=DetectCookie.find_by_remote_ip(request.remote_ip)
......detect_cookie ? redirect_to(detect_cookie.request_uri) : redirect_to(cookie_path)
....else
......redirect_back_or_default(:controller => 'apartments')
....end
..end
end
Add the following to the detect_cokkie.rb file in the models folder:
class DetectCookie < ActiveRecord::Base
..def DetectCookie.find_and_destroy_or_create_by_remote_ip(remote_ip, request_uri)
....if detect_cookie=DetectCookie.find_by_remote_ip(remote_ip)
......DetectCookie.destroy(detect_cookie.id)
......true
....else
......DetectCookie.create(:remote_ip=> remote_ip, :request_uri => request_uri)
......false
....end
..end
end
All PUT, UPDATE and DESTROY methods require the session cookie with protect_from_forgery or the application will break if a browser has cookies turned off when one of these methods are used.
Unfortunately, when a browser calls the application for the first time, the session cookie wil be written, but it wont be read untill the next page request. This makes it impossible to know if cookies are off, or of in the browser so anyone visiting the application first time and lets say, posts a form will be disapointed.
This is a simple solution to the problem. All controllers will call a cookies_required method when PUT, UPDATE or DESTROY methods are used. The cookies_required method looks to see it if the session cookie is empty - if it is, it will catch the http-referrer and redirect to the method check_for_cookies - if the session cookie is still empty, then we can be certain that cookies are off in the browser and refrain the user from using the PUT, UPDATE or DESTROY methods. Instead we show a message about cookies being off and the application having limited functionality untill they are turned on.
Add the following to application.rb
..before_filter :cookies_required, :except => [:show, :check_for_cookies]
..def check_for_cookies
....if request.cookies["_cookie_detect_session"].to_s.blank?
......render :text => 'You absolutly Need Cookies on to use this function'
....else
......redirect_back_or_default(:controller => 'home')
....end
..end
protected
..def cookies_required?
....return unless request.cookies["_cookie_detect_session"].to_s.blank?
....session[:return_to] = request.request_uri
....redirect_to(:controller => 'home',:action => 'check_for_cookies')
..end
..def redirect_back_or_default(default)
....session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
....session[:return_to] = nil
..end
Rails 2.0 + uses a cookie on the client bowser to store session data. Sesion data is used to protect against misuse and data theft.
If the client browser has cookies disabled the application with throw an exception for any and all PUT, UPDATE and DESTROY requests.
To safeguard this you should diable any code that results in PUT, UPDATE and DESTROY requests if cookies are disabled in the browser client.
Just add a protected method in the application controller.
helper_method :cookies_on?
protected
def cookies_on?
..request.cookies["_appname_session"].to_s.include?('_appname_session')
end
The "_appname_session" defalts to the name for your application and is defined in the app/config/environment.rb
config.action_controller.session = {
:session_key => '_appname_session',
:secret => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
In your controllers and views you can now write:
<% if cookies_on? %>
# show the form with the submit button
<% else %>
# show the form without the submit button and display a message telling the user that this site protects the identiy of users with coded cookies and they cannot sumbit the form without cookies enabled in the browser.
<% end %>
As the session cookie won't be avilable until the user has loaded at least two pages of your application, until then your application will be in a state of "cookies disabled".
This is all a bit of a pain, especially in the light of mobile browsers, most of which do not support cookies. However in the light of data protection, there is a real need to come up with practices to deal with this. And rails does a great job - so lets not get pissed off with rails, but more with the twits that seem to think the web is some sort of data free for all.
BTW: Setting your own cookie is as easy as
cookies [:my_name_of_cookie]="hello this string will now be in a cookie in the users browser"
The next time the user views somthing you can read the cookie:
value=cookies[:my_name_of_cookie]
puts value -> "hello this string will now be in a cookie in the users browser"