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.