我有一个托管在IIS中的服务。它由Web.config配置。
我创建了一个自定义UserNamePassValidator,如果我在validate方法中有逻辑,它就可以工作。但我想在另一个项目中使用逻辑并使用DI注入如下。
public class UserNamePassValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
private readonly ISystemAuthentication _systemAuthentication;
public UserNamePassValidator(ISystemAuthentication systemAuthentication)
{
_systemAuthentication = systemAuthentication;
}
public override void Validate(string userName, string password)
{
_systemAuthentication.Validate(userName, password))
}
}
我正在使用Autofac WCF集成。
var builder = new ContainerBuilder();
builder.RegisterType<AuthenticationService>().As<IAuthenticationService>();
builder.Register(c => new SystemAuthentication()).As<ISystemAuthentication>();
builder.Register(c => new UserNamePassValidator(c.Resolve<ISystemAuthentication>()));
AutofacHostFactory.Container = builder.Build();
当我浏览该服务时,我收到以下错误:
[MissingMethodException: No parameterless constructor defined for this object.]
web.config行为;
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
我已阅读以下相关帖子,但该示例是自托管服务: How to inject an object into a WCF validator class
修改
<system.serviceModel>
<services>
<service behaviorConfiguration="Namespace.AuthenticationServiceBehaviour" name="Namespace.AuthenticationService" >
<endpoint address="" binding="wsHttpBinding" contract="Namespace.IAuthenticationService" bindingConfiguration="SafeServiceConf">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Namespace.AuthenticationServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="AuthenticationService"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Namespace.UserNamePassValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="SafeServiceConf" maxReceivedMessageSize="65536">
<readerQuotas maxStringContentLength="65536" maxArrayLength="65536" maxBytesPerRead="65536" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
SystemAuthentication类
public class SystemAuthentication : ISystemAuthentication
{
public bool Validate(string userName, string password)
{
// removed code for abbreviation
return true;
}
WCF身份验证服务
public class AuthenticationService : IAuthenticationService
{
public bool Authenticate(string email, string password)
{
// removed for abbreviation
return true;
}
}
答案 0 :(得分:9)
在这篇文章的帮助下UserNamePasswordValidator: When DI and Framework collide
从我删除的XML配置中:
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
我将行为添加到AutoFacHostFactory服务主机
IContainer container = builder.Build();
AutofacHostFactory.Container = container;
AutofacHostFactory.HostConfigurationAction = host =>
{
var auth = host.Credentials.UserNameAuthentication;
auth.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
auth.CustomUserNamePasswordValidator = container.Resolve<UserNamePassValidator>();
};
这很好用,但是能够从web.config中做到这一点会更好。如果有人知道更好的方式,请发布:)