可以使用带有用户名/密码和客户端证书的WCF STS吗?

问题描述

| 我正在将WIF与STS一起使用。一切正常,客户端通过发送凭据中的用户名/密码进行身份验证。 我们在客户的站点上安装客户端。 我想要的是让每个客户为其客户使用自己的证书。原因是无法进行“客户站点”验证。我可以停用某些用户帐户,但不能一次禁用某个客户安装的所有客户端。 如果每个客户都有不同的证书,那么我可以吊销该证书,并且该客户的任何客户端都无法连接。 我找不到任何方法可以强制客户端将其证书设置为通信。通常,当将身份验证模式设置为证书时这是自动的,但是我需要将其设置为Windows才能发送身份验证。 有谁知道如何实现这一目标?或者让我知道这是否不可能。 干杯。     

解决方法

可以肯定的是,您只需要花一点功夫就可以从定制的安全绑定扩展元素开始,以描述令牌以及应该使用哪个进行签名/背书。为了便于说明,我假设您总是希望同时通过证书和用户名/密码。 在自定义绑定元素中,您将需要创建一个“ 0”并向其中添加令牌参数。有三个集合可向
SignedEncrypted
Signed
Endorsing
添加令牌参数。对于我们在这里讨论的场景,我建议将
UserNameSecurityTokenParameters
添加到
SignedEncrypted
集合中,并将
X509SSecurityTokenParameters
添加到
Endorsing
集合中。这意味着消息的有效性/完整性由证书令牌提供,而不是由用户名/密码提供,并且用户名/密码令牌将由证书令牌签名和加密。看起来类似于以下内容:
public class MySecurityBindingElement : BindingElementExtensionElement
{
    public override void ApplyConfiguration(BindingElement bindingElement)
    {
        base.ApplyConfiguration(bindingElement);

        TransportSecurityBindingElement transportSecurityBindingElement = (TransportSecurityBindingElement)bindingElement;

        transportSecurityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());

        transportSecurityBindingElement.EndpointSupportingTokenParameters.Endorsing.Add(new X509SecurityTokenParameters
        {
            InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient,ReferenceStyle = SecurityTokenReferenceStyle.Internal,RequireDerivedKeys = false,X509ReferenceStyle = X509KeyIdentifierClauseType.Any
        });         
    }

    protected override BindingElement CreateBindingElement()
    {
        TransportSecurityBindingElement result = new TransportSecurityBindingElement
        {
            IncludeTimestamp = true,LocalClientSettings.DetectReplays = false,LocalServiceSettings.DetectReplays = false
        };

        this.ApplyConfiguration(result);

        return result;
     }
}
然后,从客户端的角度来看,您只需确保为与服务器进行通信的每个通道都设置了证书和用户名密码即可。您可以在运行时通过设置
ChannelFactory
或标准WCF
ClientBase
代理类的
Credentials
属性上的属性来执行此操作。您可以做的另一件事是通过端点行为设置客户端证书,如下所示:
<endpointBehavior>
    <behavior name=\"MyBehavior\">
        <clientCredentials>
            <clientCertificate findValue=\"MySubject\" x509FindType=\"FindBySubjectName\" storeLocation=\"LocalMachine\" storeName=\"My\" />
        </clientCredentials>
    </behavior>
</endpointBehavior>
这样,您只需在运行时显式设置用户名/密码即可。 最后,在STS上,您可以通过
OperationContext::SupportingTokens
属性读取用户指定的令牌。您将在集合中找到
UserNameSecurityToken
X509SecurityToken
的实例,然后您可以使用这些实例对调用方进行身份验证。