Introduction
Tried recently to secure some data beans, followed WebSphere Commerce infocenter and didn't manage to make it work ? banged your head against a brick wall for hours and still didn't work ? Welcome in club, you are not alone.Assumptions
Let's assume we have the following details to start with:- Data bean to secure is com.mycompany.beans.SampleDataBean
- The bean is declared as follows
public class SampleDataBean extends SmartDataBeanImpl
- The bean is intended for administrators only and should be available for members of group CSRSystemAdmins
Steps
- Change your bean to implement both Protectable & Delegator as shown below
public class SampleDataBean extends BaseSearchBean implements Protectable, Delegator
- Implement getDelegate as shown below. This method is the most important for security to work and most properly, things didn't work for you because you didn't implement getDelegate and left it to just return null, which for Commerce (DataBeanManager to be more specific) means security will be ignored (even if you defined access policies). You need to return a reference to any object that implements Protectable and since my sample implements it, I will return a reference to it (which is this).
@Override
public Protectable getDelegate() throws Exception {
String METHOD_NAME = "getDelegate()";
LOGGER.entering(CLASS_NAME, METHOD_NAME);
return this;
}
- You can leave fulfills without a particular implementation as shown below. In the sample scenario explained here, I enabled tracing and am sure fulfills was never called during bean initialization which means it will not impact how am expecting bean to work. On other hand, if you are doing more changes and you will define a relation between policy and resource, then you need to have a proper implementation.
@Override
public boolean fulfills(Long member, String relationship) throws Exception, java.rmi.RemoteException {
String METHOD_NAME = "fulfills(Long member, String relationship)";
LOGGER.entering(CLASS_NAME, METHOD_NAME);
return false;
}
- Implement getOwner as shown below. Again it doesn't make a big difference, I just decided that the owner is whoever executing it. You can change it to whatever you see more appropriate.
@Override public Long getOwner() throws Exception, java.rmi.RemoteException { String METHOD_NAME = "getOwner()"; LOGGER.entering(CLASS_NAME, METHOD_NAME); return getCommandContext().getUserId(); }
- Now for access policies, you need to amend your access policies to have something as shown below. I marked in red, the pieces you need to focus on while adding the new access policy. Remember the order of the sections below is important.
<Action Name="DisplayDatabean" CommandName="Display"/>
<ActionGroup Name="DisplayDatabeanActionGroup" OwnerID="RootOrganization"><ActionGroupAction Name="DisplayDatabean"/></ActionGroup> <ResourceCategory Name="SampleDataBean" ResourceBeanClass="com.mycompany.beans.SampleDataBean"><ResourceAction Name="DisplayDatabean"/></ResourceCategory> <ResourceGroup Name="DataBeansForAdmins" OwnerID="RootOrganization"><ResourceGroupResource Name="SampleDataBean"/></ResourceGroup> <Policy Name="DisplayDataBeansForAdmins"OwnerID="RootOrganization"UserGroup="CSRSystemAdmins"ActionGroupName="DisplayDatabeanActionGroup"ResourceGroupName="DataBeansForAdmins"PolicyType="groupableStandard"></Policy>
- Load the new policy using acpload
- Make sure you don't have any errors in acpload.log
- Open Organization administration console and review the entries are properly loaded
- Enable access control tracing as explained in an older blog Debugging WebSphere Commerce
- Restart server
- Start testing and access your JSPs as usual. You need to access the JSPs with a guest user, a logged-in user who is not a member of group CSRSystemAdmins
- If security check is successful and user ganted access, you should something similar to the trace output below
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed isAllowed? User=344003; Action=Display; Resource=com.mycompany.beans.SampleDataBean; Owner=344003; Resource Ancestor Orgs=-2001; Resource Applicable Orgs=-2001
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed Found PolicyName: DisplayDataBeansForAdmin; PolicyType: 2; PolicyOwner: -2001
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Entry
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Policy Applicable Orgs=-2001
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Exit
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy Evaluating PolicyName: DisplayDataBeansForAdmin
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy CommandLevelCheck: false; StoreId: 10151
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy No Relationship or RelationshipGroup to check
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed PASSED? =true
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed Exit
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed PASSED? =true
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed Exit
- If on other hand, user denied access, you will see something as shown below
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed isAllowed? User=333003; Action=Display; Resource=com.mycompany.beans.SampleDataBean; Owner=333003; Resource Ancestor Orgs=-2000,-2001; Resource Applicable Orgs=-2000
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed Found PolicyName: DisplayDataBeansForAdmin; PolicyType: 2; PolicyOwner: -2001
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Entry
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Policy Applicable Orgs=-2000
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs Exit
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy Evaluating PolicyName: DisplayDataBeansForAdmin
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy CommandLevelCheck: false; StoreId: 10151
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy Normal UserGroup does not match
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed PASSED? =false
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed Exit
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed PASSED? =false
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed Exit
Final Recommendation
- It is better you always test your security by enabling trace to make sure that a user is denied or granted access for the right expected reasons and according to your expectations for how the policy should work. Sometimes you can get the right results but for wrong reasons, for example, you have another policy (that you created for sake of testing long time ago) in your local environment that happens to do what you expect. In such cases, once your code is deployed to another environment, it will stop working and it will take you a long time to figure out why.
No comments:
Post a Comment