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

VS 2022添加服务引用未为生成ClientCredentials。网络框架

  •  0
  • Mike  · 技术社区  · 1 年前

    我必须添加一个服务引用来为创建客户端代理。Net Framework服务和一个。Net 8服务。这个。Net 8添加服务引用正确生成客户端代理并执行,没有问题。在单独的基于项目/框架的服务中,生成的代理不包括ClientCredentials。

    对于wsdl中的以下策略:

      <wsp:Policy wsu:Id="WSHttpBinding_IQuery_2012_04_policy">
        <wsp:ExactlyOne>
          <wsp:All>
            <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
              <wsp:Policy>
                <sp:TransportToken>
                  <wsp:Policy>
                    <sp:HttpsToken RequireClientCertificate="false" />
                  </wsp:Policy>
                </sp:TransportToken>
                <sp:AlgorithmSuite>
                  <wsp:Policy>
                    <sp:Basic256 />
                  </wsp:Policy>
                </sp:AlgorithmSuite>
                <sp:Layout>
                  <wsp:Policy>
                    <sp:Strict />
                  </wsp:Policy>
                </sp:Layout>
                <sp:IncludeTimestamp />
              </wsp:Policy>
            </sp:TransportBinding>
            <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
              <wsp:Policy>
                <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
                  <wsp:Policy>
                    <sp:WssUsernameToken10 />
                  </wsp:Policy>
                </sp:UsernameToken>
              </wsp:Policy>
            </sp:SignedSupportingTokens>
            <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
              <wsp:Policy />
            </sp:Wss11>
            <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
              <wsp:Policy>
                <sp:MustSupportIssuedTokens />
                <sp:RequireClientEntropy />
                <sp:RequireServerEntropy />
              </wsp:Policy>
            </sp:Trust10>
            <wsaw:UsingAddressing />
          </wsp:All>
        </wsp:ExactlyOne>
      </wsp:Policy>
    

    它确实生成了正确的绑定/客户端信息:

    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IQuery_2012_04">
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" establishSecurityContext="false" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://somehost/ptsqamt/Maintain/Services/Data/2012/04/Query.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IQuery_2012_04"
                contract="PTSQueryService.IQuery_2012_04" name="WSHttpBinding_IQuery_2012_04" />
        </client>
    </system.serviceModel>
    

    生成的客户端代理不会创建ClientCredentials,因此我无法添加用户名/密码。

    为生成的客户端代码段。Net Framework参考:

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class Query_2012_04Client : System.ServiceModel.ClientBase<WCFTest.PTSQueryService.IQuery_2012_04>, WCFTest.PTSQueryService.IQuery_2012_04 {
        
        public Query_2012_04Client() {
        }
        
        public Query_2012_04Client(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }
        
        public Query_2012_04Client(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public Query_2012_04Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public Query_2012_04Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress) {
        }
        
        public WCFTest.PTSQueryService.QueryParameter[] GetQueryParameters(int qtype, string qname) {
            return base.Channel.GetQueryParameters(qtype, qname);
        }
        
        public System.Threading.Tasks.Task<WCFTest.PTSQueryService.QueryParameter[]> GetQueryParametersAsync(int qtype, string qname) {
            return base.Channel.GetQueryParametersAsync(qtype, qname);
        }
        
        public string GetQueryData(int qtype, string qname, WCFTest.PTSQueryService.QueryArgument[] args, int page, int pageSize) {
            return base.Channel.GetQueryData(qtype, qname, args, page, pageSize);
        }
        
        public System.Threading.Tasks.Task<string> GetQueryDataAsync(int qtype, string qname, WCFTest.PTSQueryService.QueryArgument[] args, int page, int pageSize) {
            return base.Channel.GetQueryDataAsync(qtype, qname, args, page, pageSize);
        }
    }
    

    作为参考,以下是。产生的净8项目:

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.2.0-preview1.23462.5")]
    public partial class Query_2012_04Client : System.ServiceModel.ClientBase<PTSQueryService.IQuery_2012_04>, PTSQueryService.IQuery_2012_04
    {
        
        /// <summary>
        /// Implement this partial method to configure the service endpoint.
        /// </summary>
        /// <param name="serviceEndpoint">The endpoint to configure</param>
        /// <param name="clientCredentials">The client credentials</param>
        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
        
        public Query_2012_04Client() : 
                base(Query_2012_04Client.GetDefaultBinding(), Query_2012_04Client.GetDefaultEndpointAddress())
        {
            this.Endpoint.Name = EndpointConfiguration.WSHttpBinding_IQuery_2012_04.ToString();
            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
        }
        
        public Query_2012_04Client(EndpointConfiguration endpointConfiguration) : 
                base(Query_2012_04Client.GetBindingForEndpoint(endpointConfiguration), Query_2012_04Client.GetEndpointAddress(endpointConfiguration))
        {
            this.Endpoint.Name = endpointConfiguration.ToString();
            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
        }
        
        public Query_2012_04Client(EndpointConfiguration endpointConfiguration, string remoteAddress) : 
                base(Query_2012_04Client.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
        {
            this.Endpoint.Name = endpointConfiguration.ToString();
            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
        }
        
        public Query_2012_04Client(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(Query_2012_04Client.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
        {
            this.Endpoint.Name = endpointConfiguration.ToString();
            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
        }
        
        public Query_2012_04Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
        
        public System.Threading.Tasks.Task<PTSQueryService.QueryParameter[]> GetQueryParametersAsync(int qtype, string qname)
        {
            return base.Channel.GetQueryParametersAsync(qtype, qname);
        }
        
        public System.Threading.Tasks.Task<string> GetQueryDataAsync(int qtype, string qname, PTSQueryService.QueryArgument[] args, int page, int pageSize)
        {
            return base.Channel.GetQueryDataAsync(qtype, qname, args, page, pageSize);
        }
        
        public virtual System.Threading.Tasks.Task OpenAsync()
        {
            return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
        }
        
        private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
        {
            if ((endpointConfiguration == EndpointConfiguration.WSHttpBinding_IQuery_2012_04))
            {
                System.ServiceModel.WSHttpBinding result = new System.ServiceModel.WSHttpBinding();
                result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
                result.MaxReceivedMessageSize = int.MaxValue;
                result.AllowCookies = true;
                result.Security.Mode = System.ServiceModel.SecurityMode.TransportWithMessageCredential;
                result.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.None;
                result.Security.Message.ClientCredentialType = System.ServiceModel.MessageCredentialType.UserName;
                result.Security.Message.EstablishSecurityContext = false;
                return result;
            }
            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
        }
        
        private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
        {
            if ((endpointConfiguration == EndpointConfiguration.WSHttpBinding_IQuery_2012_04))
            {
                return new System.ServiceModel.EndpointAddress("https://somehost/ptsqamt/Maintain/Services/Data/2012/04/Query.s" +
                        "vc");
            }
            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
        }
        
        private static System.ServiceModel.Channels.Binding GetDefaultBinding()
        {
            return Query_2012_04Client.GetBindingForEndpoint(EndpointConfiguration.WSHttpBinding_IQuery_2012_04);
        }
        
        private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
        {
            return Query_2012_04Client.GetEndpointAddress(EndpointConfiguration.WSHttpBinding_IQuery_2012_04);
        }
        
        public enum EndpointConfiguration
        {
            
            WSHttpBinding_IQuery_2012_04,
        }
    }
    

    谢谢你能提供的任何帮助。

    0 回复  |  直到 1 年前
        1
  •  0
  •   QI You    1 年前

    客户端凭据 存在于 系统。服务模型。客户群 <TChannel> .

    enter image description here

    你可以这样使用它:

    向服务器添加验证类: 公共类CustomUserNameValidator:用户名密码验证器 {

       public override void Validate(string userName, string password)
        {
            if (null == userName || null == password)
            {
                throw new ArgumentNullException();
            }
            if (userName != "admin" && password != "wcf.admin") 
            {
                throw new System.IdentityModel.Tokens.SecurityTokenException("Unknown Username or Password");
            }
    
        }
    }
    

    在客户端中使用此代码添加用户名和密码:

    using (var proxy = new ServiceReference1.Service1Client())
    {
        proxy.ClientCredentials.UserName.UserName = "admin";
        proxy.ClientCredentials.UserName.Password = "wcf.admin";
        string result = proxy.GetData(1);
        Console.WriteLine(result);
        var compositeObj = proxy.GetDataUsingDataContract(new CompositeType() { BoolValue = true, StringValue = "test" });
        Console.WriteLine(SerializerToJson(compositeObj));
    }
    Console.ReadKey();
    

    如果存在差异,则会出现错误

    enter image description here

        2
  •  0
  •   Mike    1 年前

    最后,这是一个简单的引用转换,暴露了ClientCredentials。我有点后悔自己花了这么多时间在这件事上。

    所以我实际上是从一个服务中调用这个服务的。我在主服务构造函数中实例化了引用:

    public class MainService : IMainService
    {
        private readonly IQuery_2012_04 _ptsService;
    
        public MainService()
        {
            _ptsService = new Query_2012_04Client();
            ((ClientBase<IQuery_2012_04>)_ptsService).ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["PTSServiceUser"];
            ((ClientBase<IQuery_2012_04>)_ptsService).ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["PTSServicePwd"];
            ((ClientBase<IQuery_2012_04>)_ptsService).Endpoint.Address = new EndpointAddress(ConfigurationManager.AppSettings["PTSQueryServiceUrl"]);
        }
    
        *** Snip ***
     }