Как добавить ClientCeritifcates, HTTP-запрос был запрещен со схемой аутентификации клиента "Аноним"

Я получаю следующую ошибку при вызове метода из автоматически сгенерированного прокси-класса веб-службы:

System.ServiceModel.Security.MessageSecurityException не было обработано
HResult=-2146233087 Сообщение = HTTP-запрос был запрещен в схеме аутентификации клиента "Аноним". Источник = mscorlib
StackTrace: Сервер трассировки стека: на System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest запрос, HttpWebResponse ответ, WebException responseException, HttpChannelFactory'1 завод) в System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest запрос, HttpWebResponse ответ, HttpChannelFactory" 1 фабрика, WebException responseException, ChannelBinding channelBinding) в System.ServiceModel.Channels.HttpChannelFactory'1.HttpRequestChannel.HttpChannelRequest.WaitForReply(тайм-аут TimeSpan) в системном сообщении System.ServiceModel.Channels.RequestShannel (RequestShannel.RequestShannel.RequestShannel..Dispatcher.RequestChannelBinder.Request (сообщение-сообщение, время ожидания TimeSpan) в System.ServiceModel.Channels.ServiceChannel.Call(действие String, односторонний логический метод, операция ProxyOperationRuntime, Object[] ins, выходы Object [], TimeSpan тайм-аут) в System.ServiceM.Channels.ServiceChannel.Call(Строковое действие, Булево одностороннее, Операция ProxyOperationRuntime, входы Object [], выходы Object [] в System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(метод IMethodCallMessageCall, операция ProxyOperationRuntime) в System.ServiceModel.Channels.ServiceChannelProessage regn.ExkeInIn: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(тип MessageData& msgData, Int32est)) в RPS.LoteNFe.LoteNFeSoapClient.RPS.LoteNFe.LoteNFeSoap.TesteEnvioLoteRPS(запрос TesteEnvioLoteRPSRequest) в каталоге c:\Users\Marcelo\Documents\Visual Studio 2015\Projects\RPS\RPS\ Ссылка на строку: Ссылки на сервис в RPS.LoteNFe.LoteNFeSoapClient.TesteEnvioLoteRPS(Int32 VersaoSchema, String MensagemXML) в c: \ Users \ Marcelo \ Documents \ Visual Studio 2015 \ Проекты \ RPS \ RPS \ Сервисные ссылки \ LoteNFe \ Reference.cs: строка 567 в RPS.Assinador.button5_Click(отправитель объекта, EventArgs e) в каталоге c:\Users\Marcelo\Documents\Visual Studio 2015\Projects\RPS\RPS\ Assinador.cs: строка 76 в System.Windows.Forms.Control.OnClick(EventArgs e) в System.Windows.Forms.Button.OnClick(EventArgs e) в System.Windows.Forms.Button.OnMouseUp (MouseEventArgs mevent) в System.Windows.Forms.Control.WmMouseUp (сообщение & m, кнопка MouseButtons, щелчки Int32) в System.Windows.Forms.Control.WndProc (сообщение & m) в System.Windows.Forms.ButtonBase.WndProc (сообщение & m) в System.Windows.Forms.Button.WndProc (сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Message & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc (Message & m) в System.Windows.Forms.NativeWindow.DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, Int). Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & msg) в System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManage r.FPushMessageLoop (IntPtr dwComponentID, причина Int32, Int32 pvLoopData) в System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (причина Int32, контекст ApplicationContext) в System.Windows.Forms.Application.ThreadContext reasonOnt) в System.Windows.Forms.Application.Run (форма mainForm) в RPS.Program.Main () в c:\Users\Marcelo\Documents\Visual Studio 2015\Projects\RPS\RPS\ Program.cs: строка 19 в System.AppDomain._nExecuteAssembly(сборка RuntimeAssembly, аргументы String[]) в System.AppDomain.ExecuteAssembly(строковый файл assembly, аргументы Evidence AssemblySecurity, String[]) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() в системе ()..ThreadStart_Context (состояние объекта) в System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, Boolean preserveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, Context Обратный вызов, состояние объекта, логическое preserveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, контекстный обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart() InnerException: System.Net.WebException HResult= = 2146 Удаленный сервер возвратил ошибку: (403) Запрещено. Source=System StackTrace: в System.Net.HttpWebRequest.GetResponse() в System.ServiceModel.Channels.HttpChannelFactory'1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) InnerException:

Вот как это называется

X509Certificate2 x509Certificate = new X509Certificate2();
X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = ((X509Certificate2Collection)store.Certificates).Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection collection1 = X509Certificate2UI.SelectFromCollection(collection, "Certificados disponiveis", "Selecione o certificado", X509SelectionFlag.SingleSelection);
x509Certificate = collection1[0];

LoteNFeSoapClient loteNFe = new LoteNFeSoapClient();
loteNFe.ClientCredentials.ClientCertificate.SetCertificate(x509Certificate.Subject, StoreLocation.CurrentUser, StoreName.My);
Retorno.Text = loteNFe.TesteEnvioLoteRPS(1, Assinado.Text);

Как я добавил эту ссылку на веб-сервис:

В сообществе MS Visual Studio 2013 Project > Add > Service Reference:

Окно справочной службы

Окно расширенных настроек справочника услуг

Obs: это конфиги по умолчанию. Этот веб-сервис муниципального правительства использовался для отправки электронных счетов за предоставленные транспортные или логистические услуги.

Я читал где-то, что необходимо добавить сертификат, как:

LoteNFeSoapClient loteNFe = new LoteNFeSoapClient();
loteNFe.ClientCertificates.Add(clientCertificate);

Но это невозможно, потому что:

  1. Этот автоматически сгенерированный класс веб-сервиса не наследуется от класса, который имеет этот метод ClientCertificates.Add() лайк HttpWebClientProtocol класс например.
  2. LoteNFeSoapClient() Класс уже наследуется от интерфейса, который заставляет messagecontract сопоставлять значения между запросом и ответом.
  3. В C# класс не может иметь несколько базовых классов.

Итак, что можно сделать? Заранее спасибо.

1 ответ

Решение

Решено, я просто сгенерировал прокси-класс webservice через командную строку, используя wsdl.exe, теперь этот класс наследуется от System.Web.Services.Protocols.SoapHttpClientProtocolтак что я могу добавить сертификат, используя

LoteNFe loteNFe = new LoteNFe();
loteNFe.ClientCertificates.Add(x509Certificate);

Примечание: класс, сгенерированный с помощью командной строки, полностью отличается от класса, сгенерированного с использованием интерфейса VS2013.

Другие вопросы по тегам