The technical term for user-defined security systems is "hacked".
This is not a joke.
When I first started working with J2EE, JSPs hadn't even been invented. I've worked with it almost daily ever since. I've seen banking systems, I've seen investment systems, I've even seen a military system or two.
And every last bloody one of them that did their own security had holes that an unskilled person could drive through in 15 minutes or less.
J2EE has a perfectly good security system that can block requests before they can even reach the application. It was designed by people who were formally trained in security and didn't have to do security as "just one more job" because is was their job.
And the beauty of it is that the amount of actual code you have to write (and therefore debug) is minimal, because the security is applied from the outside.
An IDE is no substitute for an Intelligent Developer.
Tim, do you know of a good resource that the average developer can use to implement container-managed security? I think the problem is that for all but the more senior developers, the resources I have seen do not do a good job of explaining how to set up security for various requirements. So it's usually easier for people to just roll their own.
Good point, Bear. Maybe we need a forum or a wiki or something.
Container security comes in 2 parts. One part is the Realm, which is part of the server. I think this is the part that most people have trouble with. All a Realm really is, however, is a mechanism that can answer 2 basic questions: 1) is a given set of credentials (userid/password) valid? 2) does the user participate in security role "X"? The hard part is attaching that mechanism to whatever service, database, LDAP server, or whatever is used to assist in answering those 2 questions.
In the application itself, virtually any basic J2EE book covers setting up secure transport, and since that mechanism is intimately intertwined with the container security definitions, usually there's some light mention of security roles as well. Unfortunately, they then ruin it by following up with an example using user-defined security.
Put simply, if you map a URL pattern for security, you can attach one or more roles to that URL pattern in the web.xml file. If a client (not yet logged in) requests that URL, the server will sidetrack the URL request, present a login screen, run it against the Realm, and then (assuming valid identification) resume the interrupted request, having built a security context (UserPrincipal) and attaching it (as well as its userID) to the incoming HTTPURLRequest object. All further incoming requests will likewise be decorated until a logout is done (via timeout or via session.invalidate()).
Although I said the incoming secured URL will be resumed, that's not totally true. The allowable roles mapped to that URL pattern are checked against the roles allotted to that user. If there's a match, the URL is dispatched. Otherwise the server rejects it. It never reaches the application or any user code or other resources. In other words, it's a declarative security mechanism.
Sometimes there's a need for determining rights within application logic. A classic example of mine is where a resource displays a web form for both data-entry personnel and for auditors. I can limit the form display and update requests to those 2 roles, but auditors are further restricted to a look-dont-touch role. In such a case, I can do things like attach "read-only" attributes to display elements based on roles using the request.isUserInRole() method and I can fine-tune actual update attempts similarly.
There's really not much more than that. For full-stack J2EE servers, the system also propagates into things like EJBs, which have their own equivalent running from the same framework, but once you know the basics, it's quite simple.
"Simpler" is no excuse for user-defined security, I'm afraid. The Internet is an ugly place these days and a security system is no stronger than its weakest link.