Не удается вызвать веб-службу с обычной проверкой подлинности с помощью WCF

мне дали веб-службу, написанную на Java, в которую я не могу внести никаких изменений. Для доступа к любому из методов требуется аутентификация пользователя с помощью обычной аутентификации. Предлагаемый способ взаимодействия с этой службой в .NET - использование Visual Studio 2005 с установленным WSE 3.0.

это проблема, так как проект уже использует Visual Studio 2008 (ориентированный на .NET 2.0). Я мог бы сделать это в VS2005, однако я не хочу связывать проект с VS2005 или делать это путем создания сборки в VS2005 и включения ее в решение VS2008 (которое в основном связывает проект с 2005 в любом случае для любых будущих изменений в сборке). Я думаю, что любой из этих вариантов усложнит работу новых разработчиков, заставив их установить WSE 3.0 и не позволить проекту использовать 2008 и функции в .NET 3.5 в будущем... т. е. я действительно считаю, что использование WCF-это путь.

Я изучал использование WCF для этого, однако Я не уверен, как заставить службу WCF понять, что ей нужно отправлять заголовки аутентификации вместе с каждым запросом. Я получаю ошибки 401, когда я пытаюсь что-либо сделать с веб-службой.

вот как выглядит мой код:

WebHttpBinding webBinding = new WebHttpBinding();
ChannelFactory<MyService> factory = 
     new ChannelFactory<MyService>(webBinding, new EndpointAddress("http://127.0.0.1:80/Service/Service/"));
factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";

MyService proxy = factory.CreateChannel();
proxy.postSubmission(_postSubmission);

Это будет выполняться и вызывать следующее исключение:

HTTP-запрос неавторизован со схемой аутентификации клиента 'Anonymous'. Заголовок проверки подлинности полученных от сервера базовой сфере '=царство'.

и это имеет внутреннее исключение:

удаленный сервер вернул ошибку: (401) Unauthorized.

любые мысли о том, что может вызвать эту проблему, будут очень признательны.

3 ответов


первый вопрос: это SOAP или Java-сервис на основе REST, который вы пытаетесь вызвать?

прямо сейчас, с "webHttpBinding", вы используете подход на основе REST. Если служба Java является службой SOAP, вам нужно будет изменить привязку, чтобы она была "basicHttpBinding".

если это сервис на основе SOAP, вы должны попробовать это:

BasicHttpBinding binding = new BasicHttpBinding();

binding.SendTimeout = TimeSpan.FromSeconds(25);

binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = 
                              HttpClientCredentialType.Basic;

EndpointAddress address = new EndpointAddress(your-url-here);

ChannelFactory<MyService> factory = 
             new ChannelFactory<MyService>(binding, address);

MyService proxy = factory.CreateChannel();

proxy.ClientCredentials.UserName.UserName = "username";
proxy.ClientCredentials.UserName.Password = "password";

я использовал это с различными веб-сервисами и это работает большую часть времени.

Если это не сработает, вам нужно будет узнать больше о том, что ожидает Java webservice и как отправить ему соответствующую информацию.

Марк


прежде всего поместите следующее в свое приложение.config или веб.конфиг. (нет необходимости изменять это, как вы перемещаете его через среды):

<system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IConfigService">
                    <security mode="TransportCredentialOnly">
                        <transport clientCredentialType="Basic"/>
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:55283/ConfigService.svc"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IConfigService"
                contract="IConfigService" name="BasicHttpBinding_IService" />
        </client>
    </system.serviceModel>

измените атрибут contract на пространство имен.Имя интерфейса соответственно. Обратите внимание на режим безопасности = TransportCredentialOnly

теперь, чтобы программно изменить конечную точку и передать учетные данные, используйте следующий код:

            var myBinding = new BasicHttpBinding("BasicHttpBinding_IConfigService");
            var myEndpoint = new EndpointAddress("http://yourbaseurl/configservice.svc");
            var myChannelFactory = new ChannelFactory<IConfigService>(myBinding, myEndpoint);

            var credentialBehaviour = myChannelFactory.Endpoint.Behaviors.Find<ClientCredentials>();
            credentialBehaviour.UserName.UserName = @"username";
            credentialBehaviour.UserName.Password = @"password";

            IConfigService client = null;

            try
            {
                client = myChannelFactory.CreateChannel();
                var brands = client.YourServiceFunctionName();
                ((ICommunicationObject)client).Close();
            }
            catch (Exception ex)
            {
                if (client != null)
                {
                    ((ICommunicationObject)client).Abort();
                }
            }

Я добавлю к этому также на основе аналогичной проблемы, которую я только что испытал. Я автоматически сгенерировал config / proxy с VS -- но созданная им конфигурация фактически не работала.

хотя у него был режим безопасности="транспорт" установлен правильно, у него не было набора clientCredentialType="Basic". Я добавил к этому свою конфигурацию, и она все еще не работала. Затем я фактически удалил безопасность сообщений, созданную инструментом с момента обращения к службе SSL + Basic только:

<message clientCredentialType="UserName" algorithmSuite="Default" />

вуаля, это сработало.

Я не уверен, почему это повлияло, учитывая, что элемент не указал безопасность уровня сообщения... но это случилось.