swfupload, and uploading via an authenticated session.

I'm constructing a site which requires authenticated uploads. I've found the swfupload tool, which works really well with with attachment_fu. However, I'm having a heck of a time getting the uploads to work over an authenticated session.

I've implemented this code (inquirylabs.com get_session_id_from_query_string_on_post.rb) via environment.rb, but I can't get it work work properly, since I get HTTP 500 errors when I try an post to a url that has embedded URL parameters. What I'm trying to do is this:

window.onload = function () {     swfu = new SWFUpload({       upload_url : '<%= swfupload_photos_path %>?_acp_session=<%= session.session_id %>',       ...

when I try to upload the request, I see a POST in the rails log as follows:

127.0.0.1 - - [19/Jan/2008:12:41:57 Mountain Standard Time] "POST / photos/swfupload?_acp_session=BAh7CToMdXNlcl9pZGkGOg...

so the session id is being inserted into the string. However, a HTTP 500 is generated before the CGI::Session object is every instantiated, and I don't know why - there are no error messages in the log that indicate where the error is occurring.

I've tried to escape the query string, and while that seems to work 'better' (I get the 500 later in the request), it still doesn't work.

Ideally, a pointer to some demo code that implements swfUpload and session id passing would be great.

I'm on the latest released version of Rails: 2.0.2.

Bit of an update - I've changed the swfUpload javascript object to look like this now:

window.onload = function () {     swfu = new SWFUpload({       upload_url : '<%= swfupload_photos_path %>',

  post_params: {       '_acp_session' : '<%= session.session_id %>'     },        ...

which is much cleaner. However, it still doesn't work :frowning:

The issue seems to be that CGI::Session doesn't seem to be accepting the session id, since my before filter (which looks for a login id, indicating that the user has authenticated) comes up empty. I'm currently digging into CGI::Session, but as of yet, no joy.

IIRC, Rails 2 introduced security measures that will prevent sessions to be passed as parameters from now on. Now, the problem is that Flash currently offers no way of passing cookies the way Rails expects it to.

I also like using SWFUpload in my projects, so I’m really interested in a solution that doesn’t involve exposing the swfupload method as non-authenticated or using some kind of alternative authentication token like method (e.g. use a hashed value as a parameter and compare it to a hashed value in the users table).

Best regards

Peter De Berdt

I was wondering if there was something in Rails 2 that was causing my difficulties....I'm not going to give up yet, but I think for the time being a token-based solution will suffice - not entirely secure, but 'good enough' for what I'm doing....

We faced the same problem after upgrading to rails 2.0, and we have it solved in the following way.

First of all, we set the session option to allow only the upload action to accept the session id outside a cookie (in post or get format):

session :cookie_only => false, :only => %w(attachment)

then we create a session_patch.rb in config/initializers, with the following ocntent:

class CGI::Session

alias original_initialize initialize

The following code is a work-around for the Flash 8 bug that prevents our multiple file uploader

from sending the _session_id. Here, we hack the Session#initialize method and force the session_id

to load from the query string via the request uri. (Tested on Lighttpd, Mongrel, Apache)

def initialize(cgiwrapper, option = {})

#RAILS_DEFAULT_LOGGER.debug “#{FILE}:#{LINE} Session options #{option.inspect} *********************”

unless option[‘cookie_only’]

#RAILS_DEFAULT_LOGGER.debug “#{FILE}:#{LINE} Initializing session object #{cgiwrapper.env_table[‘RAW_POST_DATA’]} *********************”

session_key = option[‘session_key’] || ‘_session_id’

query_string = if (rpd = cgiwrapper.env_table[‘RAW_POST_DATA’]) and rpd != ‘’

rpd

elsif (qs = cgiwrapper.env_table[‘QUERY_STRING’]) and qs != ‘’

qs

elsif (ru = cgiwrapper.env_table[‘REQUEST_URI’][0…-1]).include?(‘?’)

ru[(ru.index(‘?’) + 1)…-1]

end

if query_string and query_string.include?(session_key)

option[‘session_id’] = query_string.scan(/#{session_key}=(.?)(&.?)*$/).flatten.first

end

end

original_initialize(cgiwrapper,option)

end

end

Hi,

For me this solution works but only with Internet Explorer 7. I have not tried the IE6 but anyway it does not work with Firefox. Has anyone invented some fix for that.

Regards, Lukasz

Hi,

For me this solution works but only with Internet Explorer 7. I have not tried the IE6 but anyway it does not work with Firefox. Has anyone invented some fix for that.

Regards, Lukasz

I got it working on Firefox 3 using Rails 2.1. I wrote up about it on my blog: http://blog.isshen.com/2008/10/5/making-swfupload-and-rails-2-1-sessions-work-together

I don't know why it doesn't work for you. You might be using cookie session store and passing the session_id in a way that screws up the Javascript.

Anyways, the PHP folks have solved it a different way, by writing a separate SWF file, pulls the session cookie in from the browser, and sets a Flash cookie.

Ho-Sheng Hsiao Isshen Solutions, Inc.

Works perfectly for me on all browsers (I use the cookie store session, but Jörg got it to work with the activerecord store too): http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/45f70281a5992fa7

Best regards

Peter De Berdt