WCF adapter - how to implement authorization?
Hi all
If I was writing a "normal" (i.e. non-BizTalk) WCF service I would lock down operations using either the PrincipalPermission attribute or do an IsInRole check in the code, but how would achieve a similar thing with the BizTalk WCF adapter (if it's even possible)?
Thanks in advance
Andy
Ответы
Yes, it is possible.
You can create your own custom service authorization behavior, and use it with WCF-Custom adapter.
I'm adding the code block below
1- Compile the code below, and install it to GAC
2- Add the following entry to machine.config file
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="myCustomAuth" type="WcfServiceBehaviors.MyCustomBehaviorElement, WcfServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLIC KEY OF YOUR DLL" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
3- Restart BTS service, and reopen administration console if it's already open.
4- Create a receive location with WCF-Custom adapter. Choose whatever binding you want. Go to behaviors tab, and add the myCustomAuth binding by right clicking on the serviceBehavior and choosing add extension
Code Blockusing
System;using
System.Collections.Generic;using
System.Text;using
System.ServiceModel;using
System.ServiceModel.Channels;using
System.ServiceModel.Description;using
System.ServiceModel.Configuration;using
System.IdentityModel.Policy;using
System.IdentityModel.Claims;using
System.Security.Principal;namespace
WcfServiceBehaviors{
public class MyCustomServiceAuthorizationManager : ServiceAuthorizationManager{
protected override bool CheckAccessCore(OperationContext operationContext){
if (!base.CheckAccessCore(operationContext)){
return false;}
AuthorizationContext authCtx = operationContext.ServiceSecurityContext.AuthorizationContext; //you can do your custom authorization here //authCtx.ClaimSets //authCtx.Properties["Principal"] //if you want to do your authorization based on the operation, you can try using operationContext.EndpointDispatcher.ContractName return true;}
}
public class MyCustomBehaviorElement : BehaviorExtensionElement{
protected override object CreateBehavior(){
return new MyCustomServiceBehavior();}
public override Type BehaviorType{
get { return typeof(MyCustomServiceBehavior); }}
}
public class MyCustomServiceBehavior : IServiceBehavior{
#region
IServiceBehavior Members public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters){
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){
ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>();authBehavior.ServiceAuthorizationManager =
new MyCustomServiceAuthorizationManager();((
IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){
}
#endregion
}
}
Все ответы
Yes, it is possible.
You can create your own custom service authorization behavior, and use it with WCF-Custom adapter.
I'm adding the code block below
1- Compile the code below, and install it to GAC
2- Add the following entry to machine.config file
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="myCustomAuth" type="WcfServiceBehaviors.MyCustomBehaviorElement, WcfServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PUBLIC KEY OF YOUR DLL" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
3- Restart BTS service, and reopen administration console if it's already open.
4- Create a receive location with WCF-Custom adapter. Choose whatever binding you want. Go to behaviors tab, and add the myCustomAuth binding by right clicking on the serviceBehavior and choosing add extension
Code Blockusing
System;using
System.Collections.Generic;using
System.Text;using
System.ServiceModel;using
System.ServiceModel.Channels;using
System.ServiceModel.Description;using
System.ServiceModel.Configuration;using
System.IdentityModel.Policy;using
System.IdentityModel.Claims;using
System.Security.Principal;namespace
WcfServiceBehaviors{
public class MyCustomServiceAuthorizationManager : ServiceAuthorizationManager{
protected override bool CheckAccessCore(OperationContext operationContext){
if (!base.CheckAccessCore(operationContext)){
return false;}
AuthorizationContext authCtx = operationContext.ServiceSecurityContext.AuthorizationContext; //you can do your custom authorization here //authCtx.ClaimSets //authCtx.Properties["Principal"] //if you want to do your authorization based on the operation, you can try using operationContext.EndpointDispatcher.ContractName return true;}
}
public class MyCustomBehaviorElement : BehaviorExtensionElement{
protected override object CreateBehavior(){
return new MyCustomServiceBehavior();}
public override Type BehaviorType{
get { return typeof(MyCustomServiceBehavior); }}
}
public class MyCustomServiceBehavior : IServiceBehavior{
#region
IServiceBehavior Members public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters){
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){
ServiceAuthorizationBehavior authBehavior = serviceDescription.Behaviors.Find<ServiceAuthorizationBehavior>();authBehavior.ServiceAuthorizationManager =
new MyCustomServiceAuthorizationManager();((
IServiceBehavior)authBehavior).ApplyDispatchBehavior(serviceDescription, serviceHostBase);}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){
}
#endregion
}
}
Many thanks for your help.
I was already on the right lines before starting this thread - I had already implemented my own IAuthorizationPolicy (where I create the principal and populate its roles), and had also tried implementing a custom ServiceAuthorizationManager class, but I just couldn't find a way to access the principal object until I saw your code.
Regards
Andy

