开发者

Varying WCF Security Roles/Claims by Method Parameter

I have a class that implements IAuthorizationPolicy. I set up a custom Principal object based on the logged in user which has all of my base level roles (I have also done this using claims). Now I would like to change the roles that a particular principal has depending on a key value passed in as a message parameter.

The problem I am having is that the request message cannot be read in the authorization policy class because I don't have access to write the message back to the request context. I c开发者_如何学Goan copy and read the message in a ServiceAuthorizationManager derived class using an override of the CheckAccess method. However, I have to ensure that the GetAuthorizationPolicies method has already been called prior to doing that.

I am looking for suggestions on how I can vary the roles on a principal, based on whether or not the message contains a particular parameter. Basically, when the Evaluate method id called on the policy I want to do something like this:

string myObjectId = null;

if (!messageCopy.IsEmpty)
{
    System.Xml.XmlDictionaryReader xdr = messageCopy.GetReaderAtBodyContents();
    xdr.ReadToDecendant("objectId");
    if (xdr.Read())
    {
        myObjectId = xdr.ReadContentAsString();
    }
    xdr.Close();
}
messageCopy.Close();

ClaimSet claims = (myObjectId != null) ?
    MapClaims(identity, myObjectId) : MapClaims(identity);

DefaultPrincipal principal = new DefaultPrincipal(identity, claims);


After an entire day of attempted failures, I gave up on trying to read the message body and used an easier method, adding a SOAP message header. When calling the service I now perform the following:

using (new OperationContextScope((IContextChannel)myService)) {
    OperationContext.Current.OutgoingMessageHeaders.Add(
        MessageHeader.CreateHeader("objectId", "http://tempuri.org/", "object value"));
    myService.BeginMyOperation(parm, callback, state);
}

Then in my service authorization policy's Evaluate method I do this:

int index = OperationContext.Current.IncomingMessageHeaders.FindHeader(
    "objectId", "http://tempuri.org/");

string myObjectId = (index < 0) ? null : 
    OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(index);

ClaimSet claims = (myObjectId != null) ?
    MapClaims(identity, myObjectId) : MapClaims(identity);

DefaultPrincipal principal = new DefaultPrincipal(identity, claims);


I run into the same situation while developing WebAPI security and I choosen the next approach:

  • Method that recieves argument creates AuthorizationContext where it passes the argument as Resource claim
  • My custom ClaimsAuthorizationManager then can get argument from AuthorizationContext.Resource and use it from authorization.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜