Implementing access control in controller commands
When creating a new controller command, the implementation class for the new command should extend the com.ibm.commerce.commands.ControllerCommandImpl class and its interface should extend the com.ibm.commerce.command.ControllerCommand interface.
About this task
For command-level access control policies for controller
commands, the interface name of the command is specified as a resource.
In order for a resource to be protected, it must implement the Protectable
interface. According to the WebSphere Commerce programming model,
this is accomplished by having the command's interface extend from com.ibm.commerce.command.ControllerCommand interface,
and the command's implementation extend from com.ibm.commerce.command.ControllerCommandImpl.
The ControllerCommand interface extends com.ibm.commerce.command.AccCommand interface,
which in turn extends Protectable
. The AccCommand
interface
is the minimum interface that a command should implement in order
to be protected by command level access control.
If the command
accesses resources that should be protected, create a private instance
variable of type AccessVector
to hold the resources.
Then override the getResources
method since the default
implementation of this method returns a null value and therefore,
no resource checking occurs.
In the new getResources
method,
you should return an array of resources or of resource-action pairs
upon which the command can act. When an action is not explicitly specified,
the action defaults to the interface name of the command being executed.
The action only needs to be specified when a command is doing both a read and write operation on different instances of the same resource class. For example, in the OrderCopy command, it can read from a source order and write to a destination order. In this case, a differentiation must be made between the two actions. This is accomplished by specifying the "-Read" action for the source order, and the "-Write" action for the destination order. When the access control framework detects these actions, it automatically prepends them with the interface name of the command before searching for applicable policies. In this case, the actions that will ultimately be used in the policies are the "com.ibm.commerce.order.commands.OrderCopyCmd-Read" and "com.ibm.commerce.order.commands.OrderCopyCmd-Write" actions.
Additionally,
it is recommended that the method determines if it must instantiate
the resource or if it can use the existing instance variable holding
the reference to the resource. Checking to see if the resource object
already exists can help to improve system performance. You can then
use the same instance variable, if required, in the performExecute
method
of the new controller command.
To determine if you must override the getResources method, consider the following:
- If you derive the resource based upon a predefined source of information, such as the command context, you would not need to override the getResources method. For example, the WebSphere Commerce UserRegistrationUpdate command derives the user's ID from the command context. In this case, the user is already authorized to act upon their own registration information, so the getResources method does not need to be overridden.
- If your command is arbitrarily specifying a new resource (and this resource is of a private nature), you must override the getResources method. As an example, the WebSphere Commerce OrderItemUpdate command takes an order ID as an input parameter. In this case, when the order resource is instantiated, you do not know if the user has authority to take action upon that particular resource. In this case, the getResources method is overridden.
The following is an example of the getResources
method:
private AccessVector resources = null;
public AccessVector getResources() throws ECException {
if (resources == null) {
OrderAccessBean orderAB = new OrderAccessBean();
orderAB.setInitKey_orderId(getOrderId().toString());
resources = new AccessVector(orderAB);
}
return resources;
}
As an example, consider the OrderItemUpdate command.
The getResources
method of this command returns one
or more Order objects (which are protectable), when it is updating
existing orders. Since the action is not specified, the action defaults
to the interface for the OrderItemUpdate command.
Multiple
resources may be returned by the getResources
method.
When this occurs, a policy that gives the user access to all of the
specified resources must be found if the action is to be carried out.
If a user had access to two out of three resources, the action may
not proceed (three out of three are required).
If you need
to perform additional parameter checking or resolving of parameters
in the controller command, you can use the validateParameters()
method.
Use of this method is optional.
Additional resource level checking
It is not always possible to determine
all of the resources that need to be protected, at the time the getResources
method
of the controller command is called.
If necessary, a task command
can also implement a getResources
method to return
a list of resources, upon which the command can act.
Another
way to invoke resource level checking is to make direct calls to the
access control policy manager, using the checkIsAllowed(Object
resource, String action)
method. This method is available
to any class that extends from the com.ibm.commerce.command.AbstractECTargetableCommand
class.
For example, the following classes extend from the AbstractECTargetableCommand
class:
-
com.ibm.commerce.command.ControllerCommandImpl
-
com.ibm.commerce.command.DataBeanCommandImpl
The checkIsAllowed
method is also available
to classes that extend the com.ibm.commerce.command.AbstractECCommand
class.
For example, the following class extends from the AbstractECCommand
class:
-
com.ibm.commerce.command.TaskCommandImpl
The following shows the signature of the checkIsAllowed
method:
void checkIsAllowed(Object resource, String action)
throws ECException
This method throws an ECApplicationException if the current user is not allowed to perform the specified action on the specified resource. If access is granted, then the method simply returns.
Access control for "create" commands
Since the getResources
method
is called before the performExecute
method in a command,
a different approach must be taken for access control for resources
that are not yet created. For example, if you have a WidgetAddCmd
,
the getResources
method cannot return the resource
that is about to be created. In this case, the getResources method
should return the container of the new resource. For example, if an
order is being created, this is done within the store resource; and
a new user is created within an organization resource.
Default implementations for command-level access control
For
command-level access control, the default implementation of the getOwner()
method returns the memberId of the store owner, if the storeId is
specified. If the storeId is not specified, the memberId of the root
organization is returned (memberId = -2001
).
The
default implementation of the getResources()
method
returns null
.
The default implementation of
the validateParameters()
does nothing.