我们在 WCF 中使用自定义绑定来使用安全令牌 (SAML) 进行身份验证。我们发现我们正在获取服务器端并看到 TokenHandler(派生自 Saml11SecurityTokenHandler)正确处理和授权令牌,然后返回一个新的 ClaimsIdentity。
但是,当处理随后调用 AuthorisationManager.CheckAccessCore(从 IdentityModelServiceAuthorizationManager 派生)时, operationContext.ServiceSecurityContext.PrimaryIdentity 是一个没有填充任何内容的 GenericIdentity。
我们有一个下面的绑定的http实现,它非常相似,并且工作正常,我们可以看到正在验证的令牌和正在返回的 ClaimsIdentity,然后我们观察到 AuthorisationManager 处理相同的身份并允许它们通过。
netTcp绑定是基于代码的绑定,如下所示:
/// <summary>
/// NetTcp binding that supports a Saml token being passed
/// </summary>
public class SamlNetTcpBinding : CustomBinding
{
private readonly TcpTransportBindingElement _transportBindingElement;
private readonly BinaryMessageEncodingBindingElement _encodingBindingElement;
// private readonly SecurityBindingElement _securityBindingElement;
/// <summary>
/// Initializes a new instance of the <see cref="SamlNetTcpBinding"/> class.
/// </summary>
public SamlNetTcpBinding()
{
IssuerAddress = "http://www.myIssuerAddress.com/";
_transportBindingElement = new TcpTransportBindingElement()
{
TransferMode = TransferMode.Streamed, PortSharingEnabled = true
};
_encodingBindingElement = new BinaryMessageEncodingBindingElement();
}
/// <summary>
/// Returns a generic collection of the binding elements from the custom binding.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.Generic.ICollection`1" /> object of type <see cref="T:System.ServiceModel.Channels.BindingElement" /> that contains the binding elements from the custom binding.
/// </returns>
public override BindingElementCollection CreateBindingElements()
{
return new BindingElementCollection()
{
new TransactionFlowBindingElement(TransactionProtocol.WSAtomicTransactionOctober2004),
CreateSecurityBindingElement(),
new SslStreamSecurityBindingElement(),
_encodingBindingElement,
_transportBindingElement
};
}
/// <summary>
/// Provide definition for the scheme.
/// </summary>
/// <returns>The URI scheme for transport used by the custom binding; or an empty string if there is no transport (<see cref="T:System.ServiceModel.Channels.TransportBindingElement" /> is null).</returns>
public override String Scheme
{
get { return "net.tcp"; }
}
/// <summary>
/// Gets or sets the issuer address.
/// </summary>
/// <value>
/// The issuer address.
/// </value>
public string IssuerAddress { get; set; }
/// <summary>
/// Create client side binding certificate.
/// </summary>
/// <returns>A security Binding element</returns>
private SecurityBindingElement CreateSecurityBindingElement()
{
var protectionParameters = new X509SecurityTokenParameters(
X509KeyIdentifierClauseType.Thumbprint, SecurityTokenInclusionMode.AlwaysToRecipient);
// Configure token issuance parameters.
var parameters = new IssuedSecurityTokenParameters(
SecurityTokenTypes.OasisWssSaml11TokenProfile11,
new EndpointAddress(IssuerAddress),
new BasicHttpBinding())
{
KeyType = System.IdentityModel.Tokens.SecurityKeyType.BearerKey,
InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient
};
var element = SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(parameters);
element.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
element.EndpointSupportingTokenParameters.Endorsing.Add(protectionParameters);
return element;
}
}
非常感谢任何想法或建议。由于 .net 管道处理了大量的编排 - 很难确定身份丢失的位置。我相当有信心 System.ServiceModel 正在某个地方丢失它,但不明白的是为什么 net.tcp 传输会导致这种情况,而 http 不会。
谢谢