Не удается вызвать веб-службу с обычной проверкой подлинности с помощью 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" />
вуаля, это сработало.
Я не уверен, почему это повлияло, учитывая, что элемент не указал безопасность уровня сообщения... но это случилось.