106 lines
3.6 KiB
Markdown
106 lines
3.6 KiB
Markdown
+++
|
|
date = "2011-03-27"
|
|
title = "Rails 3 + Devise + Uploadify = No Flash Session Hacks"
|
|
tags = ["Rails", "rails3", "devise", "uploadify", "flash"]
|
|
slug = "rails-3-devise-uploadify-no-flash-session-hacks"
|
|
+++
|
|
Uploadify is a great project to provide file uploads in your project.
|
|
The problem is, it's written in flash.
|
|
|
|
Besides the point that _it is flash_, there's something else that has
|
|
been bothering me a lot: **sessions**.
|
|
~
|
|
The problem is like this. When a browsers opens a connection to your
|
|
Rails app, it has a session. Normally, session information is stored a
|
|
cookie that is sent with every request. This session also contains
|
|
information needed for you to stay logged in as a particular user.
|
|
|
|
If you embed Flash on your site and have it communicate with your Rails
|
|
application, it will start a new session. Basically, Flash just acts
|
|
as a whole other browser.
|
|
|
|
Because of this behaviour, when a logged in user uploads files with
|
|
Uploadify, the uploads will appear to come from an unauthenticated
|
|
user. There is no session information provided by flash to identify
|
|
that a user is signed in.
|
|
|
|
**The _old_ solution**
|
|
|
|
The old solution I've found around the web is to work around this
|
|
session problem by forcing flash to send the browser's session
|
|
information. This solution also requires you to add a piece of _rack
|
|
middleware_ to your app that takes any requests from a flash client and
|
|
hacks the session to look like it came from the browser.
|
|
|
|
Besides the fact that I couldn't get this hack to work, it still is
|
|
a big hack. So, what to do?
|
|
|
|
**A word on devise**
|
|
|
|
I happen to use Devise in my app to authenticate users. As you may know,
|
|
Devise is _very_ complete. It includes everything ranging from sign up,
|
|
forgotten passwords and even account locking. It also features _token
|
|
authentication_.
|
|
|
|
Token authentication means that a user can authenticate himself by
|
|
providing a unique token, in most cases a string of random characters.
|
|
|
|
A common use case for this token authentication is to provide users with
|
|
a _secret link_ to an RSS feed, or to allow quick access to the
|
|
application from link sent in an email. You click the link and you're
|
|
automagically logged in.
|
|
|
|
**The _new_ solution**
|
|
|
|
So, this token authentication got me thinking. Instead of sending an
|
|
encoded string with session information to flash, which in turn sends it
|
|
to the server, which in turn hacks it into an actual session, I could
|
|
just send the user's authentication token along! No sever-side hacks
|
|
required - it's all built in into devise already!
|
|
|
|
Let me show you. First check that your (devise-powered) user has an
|
|
authentitication token:
|
|
|
|
``` ruby
|
|
@user.authentication_token
|
|
=> "4R2bzzQRdoT_iz-ND4Bb"
|
|
```
|
|
|
|
In case your `authentication_token` is nil, you should generate one with
|
|
`@user.reset_authentication_token!`
|
|
|
|
The next step is to tell Flash to use this authentication token in its
|
|
request to the server (while uploading files). Nothing fancy here
|
|
either. Not that this is a snippet from JavaScript, embedded in a HAML
|
|
template:
|
|
|
|
``` javascript
|
|
$('#image_file').uploadify({
|
|
// I omitted all other config options, since they're not relevant.
|
|
'script' : '#{images_path(:auth_token => current_user.authentication_token, :format => :json)}'
|
|
)
|
|
```
|
|
|
|
Rails will generate a URL like this:
|
|
`/images.json?auth_token=4R2bzzQRdoT_iz-ND4Bb`.
|
|
|
|
The final step is to protect your `ImagesController#create` action with
|
|
devise.
|
|
|
|
``` ruby
|
|
class ImagesController < ApplicationController
|
|
before_filter :authenticate_user!
|
|
|
|
def create
|
|
# Handle your upload
|
|
end
|
|
end
|
|
```
|
|
|
|
That's all. You dont' even need to add rack middleware or hack Uploadify
|
|
to allow an authenticated devise user to upload images through flash.
|
|
|
|
Easy, huh?
|
|
|
|
|