Since parameter validation is usually the first task a programmer covers, let's look at other things you should check beyond validation.  There are three main layers of security to be checked when handling a user web request:

1) Does the user have appropriate permission to perform the action?  For example, if a user has a manager role, perhaps they are allowed to save an Invoice.  This may be a simple role/permission check for access to the action, or a more complex business rule that is driven by a query from the database.  Note that permission to perform an action like “SAVE” is not the same as having permission to display the screen prior to performing the action (you could regard the “DISPLAY” of that screen as a separate action as well).  This wide granularity check is normally covered by web container role/permission realm security (see the [security.role] role/permission section in this chapter).

2) Can the user do the action depending on the state of the data?  For example, if an Invoice already has a state of “PAID” it cannot be paid again.  This check could be implemented by creating a state machine that relates to the core business object.  It doesn't really matter how it's done, as long as the code is kept together and not scattered throughout controllers e.g.

public class InvoiceStateMachine
{
    public static boolean canTransition(Invoice invoice,  
        InvoiceState originalState,  
        InvoiceState proposedState)
    {
        :
    }
}

3) Can the user do the action depending on the ownership of the data?  For example, if it is an Invoice that the user previously created but did not submit, can they save it?  This can be rolled into a state machine, but since it usually requires a database query, a new class will have to exist on the application tier of the solution.

Where these checks will be happening in many places, or where the checks are particularly complex, it is best to define them in one place to ensure consistency and reliability.  Perhaps a SecurityHelper class, at least until you decide on a better, more granular place for the code to live.

blog comments powered by Disqus