Whenever a user interacts with a resource while not logged in, I need to:
- Redirect them to a secure page.
- Show a signup/login dialog (which is usually partially customized based on the resource, and may have a link to a no-login version of the resource).
- Send the user to the resource (if they login).
This is a relatively common/simple problem, but unfortunately there are several wrinkles:
- There are several types of resources, each of which has a slightly different login control.
- Some of the resources require customized business logic and/or login controls.
- Some user states require customized business logic and/or login controls.
My current approach, grown organically over time by multiple developers:
- When a user requests a resource, the resource object does one or
more of the following:
A) Stuff a state object into the user's session.
B) Craft a query string based on the current state and on the requested resource.
C) Direct the user to a secure page.
- Other controls on the page detect A-C. One of these controls renders a login dialog.
- The login dialog sends the user to the resulting page.
This works, but has several problems:
- The code responsible for handling resource requests is entirely independent from the code generating the requests. Effectively, the state object is a user-specific global variable.
- The code responsible for handling resource requests for logged in users is heavily separated from the code handling resource requests for unlogged in users, even though it is heavily overlapping. Note that this is a problem of indirection (i.e., code duplication is mostly avoided in favor of layers of indirection and heavily nested calls to shared code).
- The code is somewhat fragile; there are a lot of ways it can break.
How can I clean this up? I've contemplating adding an Action (or a state machine) to the state object. This would give the resource request object has direct control over the resource result object, rather than indirect control through the login control. However, that really doesn't strike me as sufficient to simplify the logic.
Notes:
- I'm using asp.net webforms with .Net 4.0.
- I don't care if the session object is serializable.