<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>kev.in &#187; Filters</title>
	<atom:link href="http://kev.in/category/controllers/filters/feed" rel="self" type="application/rss+xml" />
	<link>http://kev.in</link>
	<description>"It was a musical thing and you were supposed to sing"</description>
	<lastBuildDate>Thu, 13 Nov 2008 09:23:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Restoring Rails session data when cookies aren&#8217;t available</title>
		<link>http://kev.in/2007/08/30/restoring-rails-session-data-when-cookies-arent-available.html</link>
		<comments>http://kev.in/2007/08/30/restoring-rails-session-data-when-cookies-arent-available.html#comments</comments>
		<pubDate>Fri, 31 Aug 2007 03:04:00 +0000</pubDate>
		<dc:creator>Kev.in</dc:creator>
				<category><![CDATA[Controllers]]></category>
		<category><![CDATA[Filters]]></category>

		<guid isPermaLink="false">http://railsauthority.com/tutorial/restoring-rails-session-data-when-cookies-arent-available</guid>
		<description><![CDATA[
If you&#8217;ve ever needed to implement user-friendly upload, you know intimately what a pain it is to get right. The web just isn&#8217;t built for uploading files from a browser. I mean, it kinda works, but even then only with a dozen or so limitations. Even the major photo and video sites have tried various [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" src="http://railsauthority.com/wp-content/uploads/cookie.jpg" title="C is for Cookie" alt="C is for Cookie" height="125" width="180" /><br />
If you&#8217;ve ever needed to implement user-friendly upload, you know intimately what a pain it is to get right. The web just isn&#8217;t built for uploading files from a browser. I mean, it kinda works, but even then only with a dozen or so limitations. Even the major photo and video sites have tried various solutions to make this easier for users. So when I built <a href="http://dibs.net">Dibs.net</a>, I decided rather quickly to abandon all hope of getting it working flawlessly with plain ol&#8217; Javascript and HTML, and instead looked into using a fairly nonintrusive Flash uploader component. (Without Flash installed, it just falls back to a simple HTML-based file-upload form.)</p>
<p>That&#8217;s not to say it was perfectly simple to get working with Rails. Because Dibs.net accepts uploads only from logged-in users, I ran into two limitations that would not allow me to use this solution:</p>
<ul>
<li>Flash doesn&#8217;t send the cookies from the browser (at least it doesn&#8217;t in Firefox; it might in IE)</li>
<li>Rails doesn&#8217;t support non-cookie sessions</li>
</ul>
<p>Because Flash doesn&#8217;t send the session cookie, Rails thinks the request is coming from a new, logged-out user and creates a new session for it. Adding a cookies feature to Flash was well out of my hands since I don&#8217;t work for Adobe, so I looked into a way to restore the session from a session key passed as a URL parameter. After some experimentation, I found a solution that works great.</p>
<p><span id="more-116"></span></p>
<h3>Assumptions</h3>
<p>I use a modified version of the <code><a href="http://technoweenie.stikipad.com/plugins/show/Acts+as+Authenticated">acts_as_authenticated</a></code> plugin. Upon authentication, the plugin sets the <code>:user</code> session key to the authenticated user&#8217;s <code>id</code>. You&#8217;ll need to adapt for your own configuration.</p>
<h3>Example Rails Code</h3>
<p class="code-source">In <span class="filename">RAILS_ROOT/app/controllers/show_my_ip_controller.rb</span>:</p>
<pre name="code" class="ruby">
class ImagesController &lt; ApplicationController
	session <img src='http://kev.in/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> ff, <img src='http://kev.in/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> nly =&gt; :create
	prepend_before_filter :restore_session_user_from_param, <img src='http://kev.in/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> nly =&gt; :create
	requires_login :except =&gt; :index

	def create
	  # Handle the file upload here
	end

	private
	def restore_session_user_from_param
	    data = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager].session_class.find_session( params[:_session_id] ).data
	    sess_obj = Marshal.load( Base64.decode64( data ) )
	    @current_user = User.find( sess_obj[:user] )
  	rescue
    	authorization_required
  	end
end</pre>
<p class="code-source">Then we include the session id as a parameter in the form&#8217;s action URL in the view:</p>
<pre name="code" class="ruby:nocontrols">
&lt;form action="&lt;%= images_path(:_session_id =&gt; session.session_id) %&gt;" method="post" id="photoupload" enctype="multipart/form-data"&gt;</pre>
<h3>How it works</h3>
<p>Under normal circumstances the <code>acts_as_authenticated</code> plugin sets the <code>@current_user</code> instance variable to the current logged-in user at the start of each request. Since we have no session data when a Flash app hits the controller, there&#8217;s effectively no <code>current_user</code>. Our goal is to get <code>current_user</code> working, so we:</p>
<ul>
<li>turn sessions off for the relevant action; otherwise Rails will create useless sessions any time Flash hits that action</li>
<li>prepend a before filter to set the <code>@current_user</code> instance variable</li>
<li>require login for most of the actions, including <code>create</code></li>
</ul>
<p>In the before_filter, we grab the session data from whatever session store we&#8217;re using, decode and unmarshall it, and set the @current_user instance variable to the <code>User</code> we find with the <code>id</code> we get from the session hash.</p>
<p>Simple? Not really. But it works!</p>
<h3>Further Reading</h3>
<p>I couldn&#8217;t find much documentation on any of this beyond stomping through the Rails code &amp; <a href="http://corelib.rubyonrails.org/classes/CGI/Session.html">Ruby&#8217;s CGI Standard Library docs</a>.</p>
<h3><strong>Update:</strong> A Word of Caution</h3>
<p>I forgot to mention when I published this earlier that there&#8217;s a reason parameterized sessions is discouraged: browsers will send the entire current link, including the session id, in referer headers to offsite hosts. This doesn&#8217;t affect Dibs.net&#8217;s Flash upload, but in other scenarios use the above with caution, or with SSL.</p>
<h3>Feedback and Article Ideas</h3>
<p>Want to see a topic explored here? <a href="/contact">Send Me a Message</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kev.in/2007/08/30/restoring-rails-session-data-when-cookies-arent-available.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

