的情况
我们正在一些WCF服务上实现不同类型的安全性。ClientCertificate,用户名&密码和匿名。
我们有两个ServiceBehaviorConfiguration,一个用于httpBinding,另一个用于wsHttpBinding。(我们有针对基于声明的安全性的自定义授权策略)作为一项要求,我们需要为每个服务提供不同的端点。3个端点使用httpBinding,1个端点使用wsHttpBinding。
一项服务的示例:
- basicHttpBinding:匿名
- basicHttpBinding:用户名和密码
- basicHttpBinding:BasicSL
- wsHttpBinding:BasicSL
注意:我们正在开发.NET 3.5
问题
第1部分:我们不能两次指定同一服务,一次使用http服务配置,一次用wsHttp服务配置。
第2部分:我们不能在端点上指定服务行为。(抛出和异常,未发现端点行为…服务行为无法设置为端点行为)
配置
对于第1部分:
<services>
<service name="Namespace.MyService" behaviorConfiguration="securityBehavior">
<endpoint address="http://server:94/MyService.svc/Anonymous" contract="Namespace.IMyService" binding="basicHttpBinding" bindingConfiguration="Anonymous">
</endpoint>
<endpoint address="http://server:94/MyService.svc/UserNameAndPassword" contract="Namespace.IMyService" binding="basicHttpBinding" bindingConfiguration="UserNameAndPassword">
</endpoint>
<endpoint address="https://server/MyService.svc/BasicSsl" contract="Namespace.IMyService" binding="basicHttpBinding" bindingConfiguration="BasicSecured">
</endpoint>
</service>
<service name="Namespace.MyService" behaviorConfiguration="wsHttpCertificateBehavior">
<endpoint address="https://server/MyService.svc/ClientCert" contract="Namespace.IMyService" binding="wsHttpBinding" bindingConfiguration="ClientCert"/>
</service>
</services>
服务行为配置:
<serviceBehaviors>
<behavior name="securityBehavior">
<serviceAuthorization serviceAuthorizationManagerType="Namespace.AdamAuthorizationManager,Assembly">
<authorizationPolicies>
<add policyType="Namespace.AdamAuthorizationManager,Assembly" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
<behavior name="wsHttpCertificateBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<serviceAuthorization serviceAuthorizationManagerType="Namespace.AdamAuthorizationManager,Assembly">
<authorizationPolicies>
<add policyType="Namespace.AdamAuthorizationManager,Assembly" />
</authorizationPolicies>
</serviceAuthorization>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck"/>
</clientCertificate>
<serviceCertificate findValue="CN=CertSubject"/>
</serviceCredentials>
</behavior>
我们如何在WsHttpBinding端点上指定不同的服务行为?或者,我们如何以不同的方式对wsHttpBinding和basicHttpBinding应用授权策略。我们将使用端点行为,但不能指定端点行为的授权策略
授权是服务级别的职责。你不能根据端点来改变它。
在高水平上,你应该:
- 定义端点绑定以使用所需的不同安全配置(您已经这样做了)
- 创建一个自定义ClaimsAuthenticationManager,以根据不同绑定将显示的不同标识分配声明
从概念上讲,ClaimsAuthenticationManager充当"服务中STS",根据不同的凭据添加声明。从那里,您可以在服务中进行基于声明的授权。
我不知道有任何可配置的授权管理器会想要你想要的,所以你必须自己写(如果你证明我错了,请发布你的发现)。
实现ClaimsAuthenticationManager需要Windows Identity Framework。下面是我使用的.NET 4.0实现的摘要(这在4.5中可能更容易)。我很抱歉代码没有编译,也不完整,但我不必花时间为公开帖子清理所有内容。不过,这应该会给你指明正确的方向。
从Microsoft.IdentityModel.Claims.ClaimsAuthenticationManager继承并实现Authenticate()。它应该看起来像这样:
namespace MyWCF.ClaimsInjection
{
public class ClaimsAuthenticationManager : Microsoft.IdentityModel.Claims.ClaimsAuthenticationManager
{
public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal == null)
{
throw new ArgumentNullException("incomingPrincipal", "ClaimInjectionClaimsAuthenticationManager requires a principal.");
}
IClaimsPrincipal resultPrincipal = base.Authenticate(resourceName, incomingPrincipal);
foreach (IIdentity identity in resultPrincipal.Identities)
{
if (identity is ClaimsIdentity)
{
// Add claims based on client cert here…
Claim identityClaim = ((ClaimsIdentity)identity).Claims.First(c => c.ClaimType == ClaimTypes.Thumbprint);
((ClaimsIdentity)identity).Claims.Add(new Claim("MyType", "Myvalue"));
}
else if (identity is WindowsClaimsIdentity)
{
// Add claims based on window group or account here…
}
// continue checking different identity types...
}
return resultPrincipal;
}
}
}
现在只需安装自定义管理器(仅包括感兴趣的部分):
<configuration>
<configSections>
<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<federatedServiceHostConfiguration />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
<microsoft.identityModel>
<service>
<claimsAuthenticationManager type="MyWCF.ClaimsAuthenticationManager, MyWCF"/>
</service>
</microsoft.identityModel>
</configuration>