It’s been a while since I posted and after dealing with this horrid bug in Flash I figured it would be a great topic to get me back on track.
So, apparently there’s this nifty little bug in Flash/ActionScript with the URLRequest object when you attempt to do a file upload, it uses a completely different browser session than the web browser or any other requests made from within Flash (image loading, sound loading, resource loading, etc.). This isn’t a problem unless you care anything about security…and unfortunately most of us do. So the project I’m currently working on uses JCIFS (http://jcifs.samba.org/) for SSO, which is actually very nice by the way, and it uses a servlet filter configured in the web.xml to authenticate the user before they ever hit the page, so by the time they reach the Servlet they’ve properly been authenticated and I don’t have to worry about rogue users.
Okay, so that all works well and good until I try to do a file upload. I try to establish a URLRequest to my JSLServlet (of course this is jSeamless) that I use for everything else, but this time I get a nifty little login prompt using basic authentication. Now, this is of course bad, but what makes it even worse is that Flash simply prompts you and then disregards it and streams the upload into the outer darkness (where there is weeping and gnashing of teeth) so the upload from the Flash perspective worked and uploaded fully (note, before I even enter anything into the login prompt) but the server never receives the upload at all. If I enter my credentials it accepts it and then disappears, but really doesn’t care anything about it.
Okay, now for the hack. Now, for you programmers that are faint of heart, don’t try this at home. For the rest of us that have to do the job no matter how dirty it might get, please forgive me for what follows…if there were another way I would have done it.
Alright, so I create a new Servlet filter called UploadOverrideFilter (yes, you see where this is going) that gets put in the filter order before the NtmlHttpFilter (JCIFS filter for SSO) that detects if the reference is made to an upload (endswith(“jslupload”) in my case). Now, what took me a bit of work to figure out is that all mechanism for referencing directly to the Servlet that the filter can pass off to is either barred or deprecated (from ServletContext there are methods for getting a Servlet, but they always return null since deprecation) so I pull out my ugly stick and turn JSLServlet into an evil beast by maintaining a static reference to “instance” that is the initted reference to the currently context JSLServlet instance. Then I simply reference that static JSLServlet instance and explicitly call doPost(…) instead of passing off to the filter chain. See the source code for yourself:
public class UploadOverrideFilter implements Filter {
public void init(FilterConfig config) {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (((HttpServletRequest)request).getRequestURI().endsWith("jslupload")) {
JSLServlet.instance.doPost((HttpServletRequest)request, (HttpServletResponse)response);
} else {
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
Yep, it’s having to write code like this that will be the death of me…a very good reason why I prefer to stick with 100% Java whenever possible is so I don’t have to write hacks like this.
Well, I guess it wasn’t as bad as it could have been, but it’s still a hack and it’s things like this that keep me up at night in the cold sweats.