我必须创建一个WCF服务(ServiceWrapper),它引用另一个WCF服务(RealService)。
我希望ServiceWrapper的客户端在身份验证请求中传递用户名/密码。
ServiceWrapper的操作调用RealService。我需要将收到的用户名/ passowrd传递给使用RealSerivce进行身份验证,然后调用其操作。
我需要在Http而不是Https(SSL / TLS)上托管服务。
问题:如何使用服务接收的客户端Credentails在不使用Https(SSL / TLS)的情况下使用引用服务进行身份验证?
答案 0 :(得分:3)
您可以使用SOAP安全性。有两个SecurityMode - Message,TransportWithMessageCredential。
您应该在<binding>
部分配置安全模式(UserName),如下所示
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="" />
<message clientCredentialType="UserName" />
</security>
接下来,您应在<behavior>
部分
<behavior name="CommonBehavior">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="True"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Megatec.MasterTourService.CustomUserNameValidator, Megatec.MasterTourService"/>
<serviceCertificate findValue="WCFServer" storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
在您的自定义验证程序中,您可以访问和存储用户名和密码,这些用户名和密码是作为ServiceWrapper的信用卡提供的。
using System.ServiceModel;
using System.IdentityModel.Selectors;
namespace MyService
{
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (!(userName == "testMan" && password == "pass"))
throw new FaultException("Incorrect login or password");
// save your Usermame and Password for future usage.
}
}
}
当您需要访问RealService时,您可以使用userName和password作为凭据,如下例所示:
private readonly Dictionary<Type, Object> channelFactoryDictionary = new Dictionary<Type, Object>();
private ChannelFactory<T> GetChannelFactory<T>() where T : class
{
if (channelFactoryDictionary.Keys.Contains(typeof(T)))
return channelFactoryDictionary[typeof(T)] as ChannelFactory<T>;
var channelFactory = new ChannelFactory<T>("*");
channelFactory.Credentials.UserName.UserName = userName;
channelFactory.Credentials.UserName.Password = password;
channelFactoryDictionary.Add(typeof(T), channelFactory);
return channelFactory;
}
答案 1 :(得分:1)
如果SSL不是一个选项,则需要使用SOAP消息安全性(SecurityMode = Message)。