Programmatic Role-Based Security

Sometimes, administrative role-based security it not granular enough for the task at hand. Consider a situation in which your application maintains a private resource (such as a database) that does not expose any public interfaces directly to the clients. You still want to allow only some callers of a method to access the resource and deny access to other callers who are not members of a specific role. The second (and more common) situation is when a method is invoked on your object and you want to know whether the caller is a member of a particular role so you can better handle the call.

To illustrate the second situation, suppose in the bank example, one of the requirements is that a customer can transfer money only if the sum involved is less than $5,000, whereas managers and tellers can transfer any amount. Declarative role-based security goes down only to the method level (not the parameter level) and can only assure you that the caller is a member of at least one of the roles you have granted access to.

To implement the requirement, you must find out the caller’s role programmatically. Fortunately, COM+ makes it easy to do just that. Remember that every method call is represented by a COM+ call object (discussed in Chapter 2). The call object implements an interface called ISecurityCallContext , obtained by calling CoGetCallContext( ) . ISecurityCallContext provides a method called IsCallerInRole( ), which lets you verify the caller’s role membership. IsCallerInRole( ), is available on IObjectContext , a legacy from MTS as well. Example 7-1 shows how to implement the new requirement using the call object security interface.

Example 7-1. Verifying the caller membership by calling ISecurityCallContext::IsCallerInRole( )

STDMETHODIMP CBank::TransferMoney(int nSum,DWORD dwAccountSrc,DWORD dwAccountDest)
{
   HRESULT hres = S_OK;
   ISecurityCallContext* pSecurityCallContext = NULL;
   _bstr_t bstrRole = "Customer" ;
   VARIANT_BOOL bInRole = FALSE;

   hres = ::CoGetCallContext(IID_ISecurityCallContext,
                             (void**)&pSecurityCallContext);
   if(pSecurityCallContext == NULL)
   {
      //No security call context available, role-based security not in use
      return E_FAIL;
   }
   hres = pSecurityCallContext->IsCallerInRole(bstrRole,&bInRole);
   pSecurityCallContext->Release(  );
   if(bInRole)//The caller is a customer
   {
      if(nSum > 5000)
         return E_FAIL;
   }
   return DoTransfer(nSum,dwAccountSrc,dwAccountDest);//Helper method
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset