View Full Version : Proxy authentication
Hi,
I'm using the WebserviceClientFactory. Several users will require proxy authentication. I've found the necessary properties in the WebserviceClient Factory:
<object id="AdvertisementWebservice" type="Spring.Web.Services.WebServiceClientFactory, Spring.Services">
<property name="ServiceUri" value="http://host/Webservices/AdvertisementWebService.asmx"></property>
<property name="ServiceInterface" value="WebservicesContracts.IAdvertisementWebService, WebservicesContracts"></property>
<property name="ProxyUrl" ref="GetProxyUrl"/>
<property name="ProxyCredential" ref="GetProxyCredentials"/>
</object>
Since proxy settings are user specific I use MethodInvokingFactory to get the settings they supply at runtime.
<object name="ProxySettings" type="View.ProxyFactory, View"/>
<object id="GetProxyUrl" type="Spring.Objects.Factory.Config.MethodInvokingFactor yObject, Spring.Core">
<property name="TargetObject" ref="ProxySettings"/>
<property name="TargetMethod" value="GetProxyUrl"/>
</object>
<object id="GetProxyCredentials" type="Spring.Objects.Factory.Config.MethodInvokingFactor yObject, Spring.Core">
<property name="TargetObject" ref="ProxySettings"/>
<property name="TargetMethod" value="GetProxyCredentials"/>
</object>
The wsdl files are loaded from the server, I believe, since retrieving the AdvertisementWebservice from the applicationcontext works.
However when I try to invoke a method I get an error that proxyauthentication is required. When I quickwatch the variable containing the webservice the proxy property returns null.
So I'm guessing the typebuilder should set the proxyvariable of my webservice. Or is that something I should do?
I hope this makes sense.
Bruno Baia
02-26-2007, 04:31 PM
Hi,
This makes sense because it was working with the old version, but it does not make sense when you think about it, there are 2 reasons :
- First, the WSDL uri and the Web Service url can be different.
You have an uri to get the WSDL contract and the Web Service url is defined in the WSDL.
Now you can also retrieve the WSDL and save it locally as a file or an embedded resource for better performance, or if your application can work offline.
<property name="ServiceUri" value="assembly://MyAssembly/MyNamespace/MyEmbeddedResource.wsdl"/>
<property name="ServiceUri" value="file://~/MyService.wsdl"/>
The web service url is defined in the WSDL document and will be used by the WebServiceClientFactory.
- Then, authentication to get the WSDL file and to use the Web Service can also be different.
Windows Authentication to get the WSDL, and then client certificate, WSE, custom soap header, etc... to access the Web Service.
So properties "ProxyUrl", "ProxyCredential" and "Credential" on WebServiceClientFactory are only used when trying to get the WSDL from an url resource ( http: https: or ftp: ).
The solution to authenticate Web Services calls is to use an aspect :
public class MyProxyAuthenticationAdvice : IMethodInterceptor
{
#region Fields
private View.ProxyFactory _proxySettings;
#endregion
#region Properties
public View.ProxyFactory ProxySettings
{
get { return _proxySettings; }
set { _proxySettings= value; }
}
#endregion
#region IMethodInterceptor Members
public object Invoke(IMethodInvocation invocation)
{
SoapHttpClientProtocol clientProtocol = invocation.This as SoapHttpClientProtocol;
if (clientProtocol == null)
{
throw new ArgumentException("The advice target should be a Web Service proxy.");
}
// Set any property on clientProtocol
#region Proxy
IWebProxy webProxy = null;
string proxyUrl = ProxySettings.GetProxyUrl();
string proxyCredential = ProxySettings.GetProxyCredentials();
if (proxyUrl != null)
{
webProxy = new WebProxy(proxyUrl);
}
if (proxyCredential != null)
{
if (webProxy == null)
{
webProxy = GlobalProxySelection.Select; // .NET 2.0
//webProxy = WebRequest.DefaultWebProxy; // .NET 1.x
}
webProxy.Credentials = proxyCredential;
}
clientProtocol.Proxy = webProxy;
#endregion
return invocation.Proceed();
}
#endregion
}
<object id="MyProxyAuthenticationAdvice"
type="MyNamespace.MyProxyAuthenticationAdvice, MyAssembly">
<property name="ProxySettings" ref="ProxySettings" />
</object>
<object id="AdvertisementWebserviceProxy" type="Spring.Web.Services.WebServiceClientFactory, Spring.Services">
<property name="ServiceUri" value="http://host/Webservices/AdvertisementWebService.asmx"></property>
<property name="ServiceInterface" value="WebservicesContracts.IAdvertisementWebService, WebservicesContracts"></property>
<property name="ProxyUrl" ref="GetProxyUrl"/>
<property name="ProxyCredential" ref="GetProxyCredentials"/>
</object>
<object id="AdvertisementWebservice" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="target" ref="AdvertisementWebserviceProxy">
</property>
<property name="interceptorNames">
<list>
<value>MyProxyAuthenticationAdvice</value>
</list>
</property>
</object>
I'm currently working on this because Spring should provide this aspects, but I got a dilemma.
I don't know if I should write one aspect for each functionality or a big aspect 'ClientProtocolConfigurationAdvice' that handles everything.
The problem is that we can have a lot of aspects and really basic : one just to set the timeout property, another one to set the CookieContainer property for stateful web services, one for each type of authentification, etc....
Bruno
Bruno Baia
02-26-2007, 04:49 PM
FYI, you can use expressions instead of MethodInvokingFactory :
<object name="ProxySettings" type="View.ProxyFactory, View"/>
<object id="AdvertisementWebservice" type="Spring.Web.Services.WebServiceClientFactory, Spring.Services">
<property name="ServiceUri" value="http://host/Webservices/AdvertisementWebService.asmx"></property>
<property name="ServiceInterface" value="WebservicesContracts.IAdvertisementWebService, WebservicesContracts"></property>
<property name="ProxyUrl">
<expression value="GetProxyUrl()">
<property name="Context" ref="ProxySettings"/>
</expression>
</property>
<property name="ProxyCredential">
<expression value="GetProxyCredentials()">
<property name="Context" ref="ProxySettings"/>
</expression>
</property>
</object>
You can also try this, but I don't know if Spring can detect that it needs to create 'ProxySettings' before evaluating the expression :
<object name="ProxySettings" type="View.ProxyFactory, View"/>
<object id="AdvertisementWebservice" type="Spring.Web.Services.WebServiceClientFactory, Spring.Services">
<property name="ServiceUri" value="http://host/Webservices/AdvertisementWebService.asmx"></property>
<property name="ServiceInterface" value="WebservicesContracts.IAdvertisementWebService, WebservicesContracts"></property>
<property name="ProxyUrl" expression="@(ProxySettings).GetProxyUrl()" />
<property name="ProxyCredential" expression="@(ProxySettings).GetProxyCredentials()" />
</object>
Bruno
Mark Pollack
02-26-2007, 05:08 PM
Hi,
Just a little tip in case ProxySettings isn't created before/by the expression evaluation is to use the depends-on (http://www.springframework.net/doc-latest/reference/html/objects.html#objects-factory-dependson) attribute.
Cheers,
Mark
Thanks for the info, didn't know that you could save the wsdl file or use expressions like that.
Don't know if I can help you with that dilemma. You could refactor each configuration (proxy, authentication,...) into its own class so you can support both the 'small' advices which call the corresponding functions they need and the 'big' advise which will use all the configuration... just my two cents.
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.