WCF basicHttpBinding 与来自 WPF 应用程序的用户名和密码
WCF basicHttpBinding with userName and password from a WPF app
我已经阅读了 SO 中的一些问题和一些链接教程。
我已经完成了所有的事情,但是我有一个问题...身份验证不起作用..只有当我发送一个随机用户名时才会出现异常,而不考虑密码。
我想,也许吧,因为我编写的验证器从未被调用过(我给它设置了断点)...但是为什么呢?
这是我的app.confing的wcf:
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="userName" value="piero"/>
<add key="password" value="piero"/>
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- Quando si distribuisce il progetto della libreria di servizi, è necessario aggiungere il contenuto del file di configurazione al file
app.config dell'host. System.Configuration non supporta i file di configurazione delle librerie. -->
<system.serviceModel>
<!--<standardEndpoints/>-->
<bindings>
<basicHttpBinding>
<binding name="usernameHttps">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="calc.CalcService" behaviorConfiguration="customBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration=""
name="base" contract="calc.ICalcService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
<endpoint address="web" behaviorConfiguration="webHttp" binding="webHttpBinding"
bindingConfiguration="" name="web" contract="calc.ICalcService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/calc/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior >
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
<behavior name="customBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="calc.CustomPass, calc"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
</system.serviceModel>
这是调用 wpf 应用程序的配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<!--<binding name="base" />-->
<binding name="base">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/calc/"
binding="basicHttpBinding" bindingConfiguration="base" contract="calcTest.ICalcService"
name="base" />
</client>
</system.serviceModel>
<appSettings>
<add key="userName" value="aaa"/>
<add key="password" value="bbb"/>
</appSettings>
</configuration>
这是 wcf 的验证器:
public class CustomPass : UserNamePasswordValidator //System.IdentityModel.dll
{
private const string USERNAME_ELEMENT_NAME = "userName";
private const string PASSWORD_ELEMENT_NAME = "password";
private const string FAULT_EXCEPTION_MESSAGE = "UserName or Password is incorrect!";
public override void Validate(string userName, string password)
{
//Guarder.Guard.ArgumentNotNull(userName).ArgumentNotNull(password);
var validateUserName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME];
var validatePassword = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME];
var validateCondition = userName.Equals(validateUserName) && password.Equals(validatePassword);
if (!validateCondition)
{
throw new FaultException(FAULT_EXCEPTION_MESSAGE);
}
}
}
所以:
- wcf 服务正确启动;
wpf 应用调用它 (basicHttpBinding) 并使用它但是:
如果没有用户名,它会从 wcf 获取错误(我认为这没问题)
wcf 服务接受所有用户名,不仅是我在验证器中设置的用户名
- 密码没用,什么都能发,但好像只有用户名
以某种方式阅读但 wcf
如何使用我的验证器?为什么它不启动?
我这样调用wcf(有什么错误吗?):
private void Add(object sender, RoutedEventArgs e)
{
var n1 = this.opOne.Text.ToString();
var n2 = this.opTwo.Text.ToString();
var calc = new calcTest.CalcServiceClient();
calc.ClientCredentials.UserName.UserName = "piero";
calc.ClientCredentials.UserName.Password = "piero";
this.res.Text = calc.Add(n1, n2);
}
你能调试 "Service.Open()" - 方法吗?
在那里您将看到您的 CustomBehavior 是否已添加到服务的 Behavios 中。您必须调用行为方法,并调用 CustomPasswordValidator。
因此您需要编写一个扩展 ServiceBehavior 的 CustomBehavior,然后调用四种方法之一(Valdate、AddBindingParameters 等...)
您需要找出调用 PasswordValidator 的位置。
我认为它在您的服务绑定的 BindingElementCollection 的 SecurityBindingElement 中(哇,这是什么句子)。接下来您必须添加 CustomBehavior(app.config 或直接在代码中)。也许您需要将绑定转换为 CustomBinding 才能更改 SecurityBindingelement 的元素。
我希望这能帮助您解决 CustomPasswordValidator 的问题。
我已经阅读了 SO 中的一些问题和一些链接教程。
我已经完成了所有的事情,但是我有一个问题...身份验证不起作用..只有当我发送一个随机用户名时才会出现异常,而不考虑密码。
我想,也许吧,因为我编写的验证器从未被调用过(我给它设置了断点)...但是为什么呢?
这是我的app.confing的wcf:
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="userName" value="piero"/>
<add key="password" value="piero"/>
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- Quando si distribuisce il progetto della libreria di servizi, è necessario aggiungere il contenuto del file di configurazione al file
app.config dell'host. System.Configuration non supporta i file di configurazione delle librerie. -->
<system.serviceModel>
<!--<standardEndpoints/>-->
<bindings>
<basicHttpBinding>
<binding name="usernameHttps">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="calc.CalcService" behaviorConfiguration="customBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration=""
name="base" contract="calc.ICalcService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
<endpoint address="web" behaviorConfiguration="webHttp" binding="webHttpBinding"
bindingConfiguration="" name="web" contract="calc.ICalcService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/calc/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior >
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
<behavior name="customBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="calc.CustomPass, calc"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
</protocolMapping>
</system.serviceModel>
这是调用 wpf 应用程序的配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<!--<binding name="base" />-->
<binding name="base">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/calc/"
binding="basicHttpBinding" bindingConfiguration="base" contract="calcTest.ICalcService"
name="base" />
</client>
</system.serviceModel>
<appSettings>
<add key="userName" value="aaa"/>
<add key="password" value="bbb"/>
</appSettings>
</configuration>
这是 wcf 的验证器:
public class CustomPass : UserNamePasswordValidator //System.IdentityModel.dll
{
private const string USERNAME_ELEMENT_NAME = "userName";
private const string PASSWORD_ELEMENT_NAME = "password";
private const string FAULT_EXCEPTION_MESSAGE = "UserName or Password is incorrect!";
public override void Validate(string userName, string password)
{
//Guarder.Guard.ArgumentNotNull(userName).ArgumentNotNull(password);
var validateUserName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME];
var validatePassword = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME];
var validateCondition = userName.Equals(validateUserName) && password.Equals(validatePassword);
if (!validateCondition)
{
throw new FaultException(FAULT_EXCEPTION_MESSAGE);
}
}
}
所以:
- wcf 服务正确启动;
wpf 应用调用它 (basicHttpBinding) 并使用它但是:
如果没有用户名,它会从 wcf 获取错误(我认为这没问题)
wcf 服务接受所有用户名,不仅是我在验证器中设置的用户名
- 密码没用,什么都能发,但好像只有用户名
以某种方式阅读但 wcf
如何使用我的验证器?为什么它不启动?
我这样调用wcf(有什么错误吗?):
private void Add(object sender, RoutedEventArgs e)
{
var n1 = this.opOne.Text.ToString();
var n2 = this.opTwo.Text.ToString();
var calc = new calcTest.CalcServiceClient();
calc.ClientCredentials.UserName.UserName = "piero";
calc.ClientCredentials.UserName.Password = "piero";
this.res.Text = calc.Add(n1, n2);
}
你能调试 "Service.Open()" - 方法吗?
在那里您将看到您的 CustomBehavior 是否已添加到服务的 Behavios 中。您必须调用行为方法,并调用 CustomPasswordValidator。
因此您需要编写一个扩展 ServiceBehavior 的 CustomBehavior,然后调用四种方法之一(Valdate、AddBindingParameters 等...) 您需要找出调用 PasswordValidator 的位置。
我认为它在您的服务绑定的 BindingElementCollection 的 SecurityBindingElement 中(哇,这是什么句子)。接下来您必须添加 CustomBehavior(app.config 或直接在代码中)。也许您需要将绑定转换为 CustomBinding 才能更改 SecurityBindingelement 的元素。
我希望这能帮助您解决 CustomPasswordValidator 的问题。