Security: Worry About That Later
Adam
I recently found myself discussing Aspect Oriented Programming (AOP) with my coworker Nathan Mische, and had one of those moments where a lightbulb turns on in your head. We came to the conclusion that when building web services and APIs in general, it may be best to initially take the approach that I'm calling "just make it work." You can worry about security and error conditions later.
Now, don't take that the wrong way. I'm not advocating no security and not checking for error conditions. There are two kinds of later: The "later" in which you plan to write the documentation, and the "later" that actually exists. When I say worry about security later, I'm referring to the one that actually exists.
Here's the thing… error conditions—including security errors—are usually cross-cutting concerns. That was my lightbulb thought. Of course, cross-cutting concerns are the bread and butter of AOP, and if you extrapolate on the thought a little bit, what it really says is that the method should only handle the best-case scenario; and that your AOP advisors should handle any errors or less-than-best-case scenarios. In fact, since I'm creating a new development methodology on the fly here, I'm going to go ahead and declare that rule #1 of just make it work: API methods should only handle the best-case scenario. Of course, rules are made to be broken, there's an exception to every rule, blah blah blah. So maybe consider it a rule of thumb.
Let's look at a real world example that (for once!) doesn't use logging as the cross-cutting functionality built with AOP.
Assume you're writing a game that simulates stock trading. Your players each represent a company with stock being traded in one of a few available markets. Each player has some cash and stocks to start with, and their goal is to make money buying and selling stocks in available markets. Of course, you can't allow insider trading, so you have to prevent players from buying and selling their own company's stock.
Start with the obvious things, methods for buying and selling stocks:
remote boolean function sellStock(playerObj, marketId, stockId, offerPrice, shares){...}
remote boolean function buyStock(playerObj, marketId, stockId, shares, maxBidPrice){...}
The contents of these functions aren't important. Write them assuming that the player has enough money to complete the purchase, enough shares to sell the number attempted, and so on… the best-case scenario. Not worrying about player's cash reserves, shares owned, and right to trade the stock frees up your mind to just make it work, which—for me, at least—can lead to increased productivity. At this point you should be tearing through your spec implementing everything you need to do, not worrying about the little details that can cause problems, and pretty soon you find yourself with a complete best-case-handling API.
After your best-case API is complete (this is the "later" that exists), think about things that can go wrong. Not enough cash to perform the transaction? Throw an error. Player isn't allowed to trade on the requested market? Throw an error. And so on.
And since these sorts of conditions are things you want to check for in a majority of your API, using AOP to write them once and apply them to the applicable API methods means you'll have more maintainable code, and your errors will be consistent across all methods (no more "401 Unauthorized" from one method and "401 Not Authorized" from another…), making it easier for your API consumers (and you should be one of them) to handle thrown errors.
And if you ever do get around to writing that documentation, your advisors will provide a centralized list of what is and isn't allowed to happen.
Posted in AOP |
0 comments


