Sunday, March 27, 2011

PreparedStatements escape their arguments.



String sql = "select * from myTable where sometext=?";


PreparedStatement prep;


...


prep.setString(1, "I'm in yur SQL");


out.println(prep.toString());

>select * from myTable where sometext='I\'m in yur SQL'


I was 'pre-escaping' the 'sometext' string before hand, which means a 'double' escaping happens, causing the query to break.


I originally thought it magically stored the string and I didn't need escaping at all, but I messed up another part of the query, leading me down the wrong path. Argh!


Pro-tip, use TOAD, or similar tool (MySQL Workbench) to verify your queries.  The preparedStatement.toString() will spit out the query for you.



Wednesday, March 23, 2011

Firefox vs Chrome - Event variable names

Works in chrome, not firefox:

<button onclick="Foobar(evt);">

In order for firefox to work as well, the event variable MUST be named 'event'.

<button onclick="Foobar(event);>

I'm guessing webkit assumes the first arg is for the event data, and firefox probably matches the string with 'event'.


No big deal, using the word 'event' is probably a better style guide anyway.

Sunday, March 20, 2011

Caveat emptor: AWS requires apache commons

specifically:

commons-logging-1.1.1.jar
commons-httpclient-3.0.1.jar
commons-codec-1.4.jar

The SDK does not include these.
No where in the docs does it say these are required.

I wasted some time figuring this out.

My friend Trimbo says that I should be using 'maven', which would have fetched these JARs magically from the intrarwebs.

I remain skeptical, I have yet to figure out how to get my project set up correctly, its complaining it can't find a server, even though tomcat has been registered globally with Netbeans.

This list of JARs is just for S3, I have no idea what other jars might be needed if other parts of the AWS SDK are touched.

Saturday, March 19, 2011

Website Security

In building one of my first true 'internet facing' sites from the ground up, both client and server side code, I have started to put lots of thought into possible attack vectors. I'm also pretty new to this stuff, so I ask advice from my friends who have been doing this thing for longer, then I wonder why other sites I visit seemingly ignore basic security measures.

To gain some focus, I'll limit security to API and man-in-the-middle snooping. I really can't do much about 'over the shoulder' peeks or key loggers on  a user machine, or someone on the console. I can minimize impact to the system, hopefully confining the security problem to a single user.


Obfuscation and Salting
Data flows from the server to the client, and unless its a really boring static page, there is likely to be javascript running, and nowadays, some XMLHttpRequests doing GET and POSTS on a servlet API, which means data is going in both ways. Also, 'anyone' can view page source, and probably deduce how to use my servlets.

Obfuscating my APIs is probably not worth my time, though I can try to make them limited to specific functions (no running of arbitrary SQL via a 'POST" for example), and have them require validated sessions/logins.

I can however mangle or obscure the data flowing out of the server to the client, as long as the client simply relays that back without requiring any transforms on it.

For example, the client can request the top most purchased items from a store website. The server can send back 'salted' keys that only it knows how to decipher. The key space can be sparse and large, which would hopefully limit 'just add one' kinds of snooping if using a in-the-open auto-incremented key. The actual SQL tables can have regular ol' integer auto_increment keys though.

Require valid sessions to do any changes.  Using HttpSession in java, this is pretty easy. I can set any arbitrary data into the session, but this is all server side. The client doesn't know I put a user name, or access level, or anything at all into the session attributes.  Once past a typical login/password exchange, a valid session is created, and any further servlet POSTs then require a valid session.

Use HTTPS to protect sensitive data:  A certificate costs money, but if you are serious about security, fork up a few bucks a month to get a certificate. HTTPS is 'the' way to stop man-in-the-middle snooping, which is dirt simple nowadays. Anyone visiting Starbucks with a laptop and some easy-to-find software can grab all the data  being sent and received from everyone else in the room. There are bound to be other points around the internet that might also be 'wide open' for data trawling.  

But don't just stop at HTTPS for a simple login/password exchange or a credit card number. Be sure to wrap any Personal Identity data exchange in HTTPS as well. Any time a user edits or views their address, phone number, 'real name' or similar information, make sure its on HTTPS.

On the subject of passwords, never store a password as plain text in your database. Store a large hash of it instead, for example, SHA-1 or MD5. Gawker learned this lesson last year. Any website that can email you your login AND password information is storing things as plain text. Sites that have a 'reset' password option are probably storing only the hash. And of course, never send the password out to the client. You may also encourage your users to choose 'better' passwords by requiring numbers, punctuation, upper and lower case, while also reminding them not to share passwords across multiple websites.

Run a security audit: I'm gonna at least have some friends look at my code, and if the stakes were high, I might even go to a 'white hat' security firm to let them analyze code and/or try to hack their way in. A small development team might want to occasionally 'abuse' their APIs while in testing, or even hire on a smart QA  person who will play the part of a malicious user.



Saturday, March 5, 2011

Submitting a hidden form with javascript on Firefox

Chrome is either more lax, or there isn't standard covering this.

In firefox, make sure the form has a name attribute, does not have a submit button named submit, and lastly, the form must have a parent element. This last bit was a bit of a guess on my part, but this was the solution I needed.
The other two tips are from elsewhere on the web.

Chrome
var f = document.createElement("form");
//... ( add stuff to form )
f.submit();

Firefox is a bit more picky, it must have a parent, and a name:

var f = document.createElement("form");
f.name="myForm";
f.style.visibility="collapse";
document.body.appendChild( f );
//... ( add stuff to form )
f.submit();

Tuesday, March 1, 2011

How to make the GAE blobstore upload be a bit more pretty.

It was really odd to see the rather clunky blobstore 'API' amidst the rather clean APIs that make up the rest of the Java Google App Engine SDK.

While I can add an entity to the regular datastore with a few lines of code, getting a blob (1MB+) of data into the blob store is a pain.

1. ask GAE to serve up an upload URL string.
2. shove this URL into a form 'action' field.
3. attach a File Input element to the form - let the user interact with it.
4. submit the form
5. watch in horror as your 'web app' redirects after the upload completes.

So, no way to get callbacks or events to show a progress bar. My first thought was to emulate the form post with XmlHttpRequest, but send() only takes a string or a File object, not both.

One of the arguments to that "give me an upload URL" call is a callback URI. What it does is reflect your form back this URI (a servlet), but it replaces the file contents with a blob key.

However, that means a redirect, actually two, since once your servlet grabs the form data, one would probably want to go back to the main JSP or servlet page and get on with the rest of the app.

Then I remembered a dirty (?) little trick - IFrames.

The form can have a 'target' attribute set, which means that when done, it 'dumps' the results (in this case, the redirect) into the iframe, and not 'document'.

Make the iframe small and invisible, and no more 'full screen' redirects. One can then hook into the "onload" event of the iframe, and have this tell the 'parent' document that a particular file upload has completed with any javascript tricks one could want.

Even with this, there is no feedback to the user as to when things will get done, only exactly when they are done.

What this should have been is a way to get a XmlHttpRequest URL, which could then directly feed a file to the blobstore with a 'prebaked' URL containing just enough data to get the job done. it would then kick back a XML or JSON object with a blob key in it. I could then hook into the client side events, and track progress and show feedback to the user. Banging through one or two redirects is very 1998.

Amazon S3 does this better, including a groovy UI for managing content. Unfortunately, GAE does not have anything so slick.

At least fetching a blob from the blobstore is easy to do in java, and it appears to support the streaming case of fractional data fetches. Thats good because I have podcasts to serve up.