代码之家  ›  专栏  ›  技术社区  ›  CodingWithSpike

使用自定义ClientCredentials的WCF身份验证:要使用的clientCredentialType是什么?

  •  24
  • CodingWithSpike  · 技术社区  · 17 年前

    我不得不放弃基本的WCF用户名/Pwd安全性,实现我自己的自定义客户端凭据,以保存一些超出默认设置的更多信息。

    我努力了 this MSDN article ,但我错过了一些东西,因为它不起作用。

    首先,我有一些自定义ClientCredentials,它们提供了一个自定义clientcredentialsecuritytokenmanager:

    public class CentralAuthCredentials : ClientCredentials
    {
        public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager()
        {
            return new CentralAuthTokenManager(this);
        }
    }
    
    public class CentralAuthTokenManager : ClientCredentialsSecurityTokenManager
    {
        private CentralAuthCredentials credentials;
    
        public CentralAuthTokenManager(CentralAuthCredentials creds) : base(creds)
        {
            this.credentials = creds;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
        {
            if (this.IsIssuedSecurityTokenRequirement(tokenRequirement) || tokenRequirement.TokenType == CentralAuthToken.TOKEN_TYPE)
                return new CentralAuthTokenProvider(credentials.UserId, credentials.UserPassword, credentials.ImpersonateId, credentials.LoginType);
            else
                return base.CreateSecurityTokenProvider(tokenRequirement);
        }
    
        public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            outOfBandTokenResolver = null;
            if (this.IsIssuedSecurityTokenRequirement(tokenRequirement) || tokenRequirement.TokenType == CentralAuthToken.TOKEN_TYPE)
                return new CentralAuthTokenAuthenticator();
            else
                return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
        }
    
        public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
        {
            return new CentralAuthTokenSerializer();
        }
    }
    

    但是,在方法中:

    CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
    {
        ...
    }
    

    这个令牌需求.令牌类型不是我定制的代币。这就引出了我的问题 第一个问题 :WCF如何知道令牌要求是什么?

    此外,方法:

    public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
    {
        return new CentralAuthTokenSerializer();
    }
    

    在客户方面,我有:

    public class CentralAuthorizationManagerClient : ClientBase<ICentralAuthorizationManager>, ICentralAuthorizationManager, IDisposable
    {
        public PFPrincipal GenerateToken()
        {
            if (!this.ChannelFactory.Endpoint.Behaviors.Contains(typeof(CentralAuthCredentials)))
                throw new ArgumentException("Must set CentralAuthCredentials before calling this method.");
            return base.Channel.GenerateToken();
        }
    
        public PFPrincipal GenerateToken(CentralAuthToken token)
        {
            this.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
            this.ChannelFactory.Endpoint.Behaviors.Add(new CentralAuthCredentials(token));
            return this.GenerateToken();
        }
    

    在配置中:

        <behaviors>
            <endpointBehaviors>
                <behavior name="Server2ServerEndpointBehavior">
                    <clientCredentials type="MyApp.Security.CentralAuthCredentials, MyApp">
                        <clientCertificate findValue="localhost" x509FindType="FindBySubjectName" storeLocation="CurrentUser" storeName="My" />
                        <serviceCertificate>
                            <authentication certificateValidationMode="None" revocationMode="NoCheck" />
                        </serviceCertificate>
                    </clientCredentials>
                </behavior>
            </endpointBehaviors>
        </behaviors>
    
        <bindings>
            <wsHttpBinding>
                <binding name="wsHttpServer2Server">
                    <security mode="Message">
                        <message clientCredentialType="UserName" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
    

    请注意,行为的clientCredentials类型设置为“我的自定义客户端凭据”。但是,目前我仍然将绑定的clientCredentialType设置为“UserName”。这就引出了我的问题 :clientCredentialType=“”到底该怎么办如果我使用自定义凭据,是否设置为?根据MSDN,可用的 信息 没有 窗户 用户名 , 证书 .

    有什么想法吗?希望我错过了一些简单的事情?整个实现还有6个类,但是我试着只包含理解情况所需的部分。。。


    我花了一整天的时间来研究这个问题,多亏了一些消息来源,我意识到我所缺少的一部分是最后一步 this page ,将TokenParameters添加到绑定中,以便绑定知道令牌的外观。这就是我最初的第一个问题的答案:“到底是什么设置了令牌需求?”答:分配给绑定的TokenParameters。

    因此,现在我添加了以下扩展,用于设置绑定上的TokenParameters:

    public sealed class CentralAuthTokenBindingExtension : BindingElementExtensionElement
    {
        public CentralAuthTokenBindingExtension()
            : base()
        {
        }
    
        public override Type BindingElementType
        {
            get { return typeof(SymmetricSecurityBindingElement); }
        }
    
        protected override System.ServiceModel.Channels.BindingElement CreateBindingElement()
        {
            X509SecurityTokenParameters protectionParams = new X509SecurityTokenParameters();
            protectionParams.InclusionMode = SecurityTokenInclusionMode.Never;
    
            SymmetricSecurityBindingElement innerBindingElement = new SymmetricSecurityBindingElement();
            innerBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CentralAuthTokenParameters());
            //innerBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
            innerBindingElement.ProtectionTokenParameters = protectionParams;
    
            return innerBindingElement;
        }
    }
    
        <extensions>
            <bindingElementExtensions>
                <add name="CentralAuthCreds" type="MyApp.Security.Configuration.CentralAuthTokenBindingExtension, MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            </bindingElementExtensions>
        </extensions>
    
        <bindings>
            <customBinding>
                <binding name="wsHttpServer2Server">
                    <CentralAuthCreds />
                    <binaryMessageEncoding />
                    <httpTransport />
                </binding>
            </customBinding>
        </bindings>
    

    这让我更进一步。现在服务器上出现了一个新异常:

    "The security token manager cannot create a token authenticator for requirement ..."
    

    看起来WCF正在使用一些默认的令牌管理器来尝试处理我的自定义令牌,而不是我的自定义令牌处理程序(我的自定义令牌处理程序的构造函数从未被调用)。我 这是因为 ,我有以下配置:

    <endpointBehaviors>
        <behavior name="Server2ServerEndpointBehavior">
            <clientCredentials type="MyApp.Security.CentralAuthCredentials, MyApp">
    

    但是在 我没有任何等价物让它知道自定义客户端凭据。所以, 新问题


    更新#2:

    嗯,我终于猜出了更多的谜题。我只实现了一个ClientCredentials实现,认为客户端发送creds,就这样。客户机不验证服务,因此我不需要自定义ServiceCredentials。我错了。指定的ServiceCredentials从ClientCredentials验证令牌,反之亦然。所以我只需要添加一个自定义ServiceCredentials实现,它传递相同的TokenSerializer和TokenAuthenticator类。

    1 回复  |  直到 16 年前
        1
  •  1
  •   djv    11 年前

    我在处理一个应用程序时遇到了类似的问题,不幸的是,我放弃了,因为无法使用自定义凭据。我现在使用用户名/密码(客户端凭据)和证书(服务凭据),并将自定义加密的soap头添加到服务调用中,以传递其他信息,如UserID等。

    推荐文章