向 WCF + Autofac 无扩展服务添加身份验证

Posted

技术标签:

【中文标题】向 WCF + Autofac 无扩展服务添加身份验证【英文标题】:Add authentication to WCF + Autofac extensionless service 【发布时间】:2021-07-03 07:11:37 【问题描述】:

我正在寻找一种方法来为我的 WCF 服务设置简单的用户名 + 密码身份验证。它们是使用Autofac extensionless services 设置的。这意味着我的 Global.asax 看起来像这样:

public class Global : HttpApplication

    protected void Application_Start(object sender, EventArgs e)        
    
        var builder = new ContainerBuilder();
        builder.RegisterType<MyWcfService>().InstancePerLifetimeScope();
        var container = builder.Build();

        AutofacHostFactory.Container = container;
        AutofacHostFactory.HostConfigurationAction =
            host =>
            
                host.Description.Behaviors.Add(container.Resolve<MyCustomBehavior>());
            ;
        
        RouteTable.Routes.Add(new ServiceRoute("my/custom/route", new AutofacServiceHostFactory(), typeof(MyWcfService)));
    

我的 Web.config 看起来像这样:

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"></serviceHostingEnvironment>
  <behaviors>
    <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <basicHttpBinding>
    <binding maxReceivedMessageSize="10485760">
      <readerQuotas maxDepth="32" maxStringContentLength="10485760" maxArrayLength="10485760" maxBytesPerRead="10485760" />
    </binding>
    </basicHttpBinding>
  </bindings>
  <protocolMapping>
    <add binding="basicHttpsBinding" scheme="https" />
  </protocolMapping>
</system.serviceModel>

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
  <directoryBrowse enabled="true" />
</system.webServer>

如您所见,我没有任何 *.svc 文件,我的 Web.config 中也没有 &lt;services&gt; 部分来配置我的服务。现在我需要向这个服务添加基本的用户名+密码认证。我已按照this Microsoft tutorial 中的步骤进行操作,但从未调用过CustomUserNameValidator

我按照教程所做的更改是:

添加CustomUserNamePasswordValidator 将 serviceCredentials 部分添加到 Web.config 中的行为
<serviceCredentials>
  <userNameAuthentication 
    userNamePasswordValidationMode="Custom" 
    customUserNamePasswordValidatorType="My.ServiceHost.CustomUserNamePasswordValidator, My.ServiceHost"/>
</serviceCredentials>
将我在 Web.config 中的绑定更新为:
<wsHttpBinding>
  <binding name="authQuotaBinding" maxReceivedMessageSize="10485760">
    <security mode="Message">
      <message clientCredentialType="UserName" />
    </security>
    <readerQuotas maxDepth="32" maxStringContentLength="10485760" maxArrayLength="10485760" maxBytesPerRead="10485760" />
  </binding>
</wsHttpBinding>

我在本地使用 IIS Express 托管服务。为了让它发挥作用,我缺少哪一块拼图?

【问题讨论】:

【参考方案1】:

有几条信息丢失,可能是拼图中丢失的部分。

    您通过 Autofac 在所有主机上定义了自定义行为,但不清楚此自定义行为在做什么和/或这是否与您的问题有关?

    您已经定义了当用户名用于身份验证并且需要验证时使用的自定义验证器(在 serviceCredentials 部分中),但是只有当您使用 wsHttpBinding 调用您的服务时才会触发。但是,我没有看到您的服务和此绑定之间有任何联系?您确定该服务正在使用该绑定吗?还是它仍在使用您的 basicHttpBinding?通常这将在每个服务的配置中进行配置,但由于您使用的是 AutoFac,我假设 Autofac 正在将绑定的配置链接到您的服务。这可能是它出错的地方吗?

我的猜测是要么你需要在 Autofac 中指定这个,要么你可能还需要更新这部分配置:

<protocolMapping>
  <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>

进入

<protocolMapping>
  <add binding="wsHttpBinding" scheme="http" />
</protocolMapping>

或者如果你想更具体

<protocolMapping>
  <add binding="wsHttpBinding" bindingConfiguration="authQuotaBinding" scheme="http" />
</protocolMapping>

但这取决于名为 basicHttpsBinding 的绑定的定义是什么。 (似乎也没有包含在提供的信息中?)

有关protocolMapping的更多信息,请参阅:https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/protocolmapping

除此之外,您的要求也可能是使用此配置:

<wsHttpBinding>
  ...
    <security mode="TransportWithMessageCredential">
      <message clientCredentialType="UserName" />
    </security>
  ...
</wsHttpBinding>

这取决于您是想使用 SOAP 消息加密/签名来确保消息的完整性,还是对 HTTPS 提供的完整性感到满意。

根据您问题中链接的文章,您甚至可以使用 basicHttpBinding 而不是 wsHttpBinding 并使用安全模式设置为 Transport 并将传输部分的 clientCredentialType 属性设置为 Basic,例如,

<basicHttpBinding>
  ...
    <security mode="Transport">
      <transport clientCredentialType="Basic" />
    </security>
  ...
</basicHttpBinding>

有关不同安全模式的更多信息,请参阅:https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/security-of-wshttpbinding

最后,我也不建议您保留 serviceDebug 设置,该设置允许您包含为生产环境设置的异常详细信息。 (当然,这又取决于您的要求)

【讨论】:

谢谢,这让我更进一步。但是,我在教程中注意到了这条注释:“当 WCF 服务使用传输级安全性托管在 Internet 信息服务 (IIS) 中并且 UserNamePasswordValidationMode 属性设置为自定义时,自定义身份验证方案使用 Windows 身份验证的子集。那是因为在这种情况下,IIS 在 WCF 调用自定义身份验证器之前执行 Windows 身份验证。”。不幸的是,这不符合我的业务需求,因为我无法使用 Windows 身份验证。

以上是关于向 WCF + Autofac 无扩展服务添加身份验证的主要内容,如果未能解决你的问题,请参考以下文章

添加 WCF 服务引用时,HTTP 请求被客户端身份验证方案“匿名”错误禁止

Autofac + WCF REST 4.0

如何向 sharepoint 2010 中托管的 wcf 服务发出经过身份验证的请求?

ServiceRoute + WebServiceHostFactory 杀死 WSDL 生成?如何使用 ?wsdl 创建无扩展 WCF 服务

无扩展 REST WCF 服务为 PUT 方法返回 http 405

将 Windows 用户“令牌”传递给 WCF 进行身份验证