无法访问受保护的WCF服务上的WSDL

本文关键字:服务 WSDL WCF 访问 受保护 | 更新日期: 2023-09-27 18:10:10

我已经设置了一个在ASP中运行的WCF服务。. NET兼容模式,这样我就可以利用站点其他部分使用的SSO身份验证。SSO基于Jasig的CAS,我已经修改了dotNetCasClient,以便它可以与WCF服务一起工作。其思想是dotNetCasClient http模块拦截向服务发出的任何请求,并根据CAS提供的票证设置主体。

要完成这项工作,我必须拒绝所有匿名用户的访问:

<system.web>
...
<authorization>
<deny users="?" />
</authorization>
...
</system.web>

到目前为止一切都工作正常。通过身份验证的用户可以调用我的服务,而未经身份验证的用户则被拒之门外。问题是我无法通过.svc? WSDL访问我的WSDL。我只得到一个401.2。

是否有一种方法允许匿名流量访问WSDL,同时仍然拒绝匿名流量访问服务的其余部分?

我试过使用下面的变体,但它不喜欢在路径中有?wsdl。

<location path=path/to/svc?wsdl>
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

我也玩过允许匿名流量和使用PrincipalPermissionAttribute代替,但这是不可能工作的,因为我使用自定义主体通过dotNetCasClient而不是windows主体。

注意,如果我从我的网页中删除授权标签。config I再次可以访问WSDL,但这将阻止SSO身份验证正常工作。

这是我完整的web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="casServiceClientConfig" type="DotNetCasClient.Configuration.CasClientConfiguration, DotNetServiceCasClient" />
    </configSections>
<system.web>
    <compilation debug="true" targetFramework="4.5.1" />
    <httpRuntime targetFramework="4.5.1" />
    <authentication mode="Forms">
        <forms loginUrl="https://XXXX/cas/login" cookieless="UseCookies" />
    </authentication>
    <authorization>
        <deny users="?" />
    </authorization>
</system.web>
<casServiceClientConfig casServerLoginUrl="https://XXXX/cas/login"
      casServerUrlPrefix="https://XXXX/cas/"
      serverName="https://XXXX"
      notAuthorizedUrl="~/NotAuthorized.aspx"
      cookiesRequiredUrl="~/CookiesRequired.aspx"
      redirectAfterValidation="true"
      renew="false"
      singleSignOut="true"
      ticketValidatorName="Cas20"
      serviceTicketManager="CacheServiceTicketManager"
      proxyTicketManager="CacheProxyTicketManager"
  />
<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
        <remove name="DotNetCasClient" />
        <remove name="PanelScheduler" />
        <remove name="ScriptModule" />
        <remove name="FormsAuthentication" />
        <add name="DotNetServiceCasClient" type="DotNetCasClient.CasAuthenticationModule,DotNetServiceCasClient" />
    </modules>
</system.webServer>
<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
        <service name="XXXX" >
            <endpoint contract="XXXX" address="" binding="customBinding" bindingConfiguration="nonSsLAuthBinding" />
            <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true" />
                <serviceAuthorization serviceAuthorizationManagerType="XXXX, XXXX">
                    <authorizationPolicies>
                        <add policyType="XXXX, XXXX" />
                    </authorizationPolicies>
                </serviceAuthorization>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <extensions>
        <bindingElementExtensions>
            <add name="nonSslAuthTransport" type="XXXX, XXXX"/>
        </bindingElementExtensions>
    </extensions>
    <bindings>
        <customBinding>
            <binding name="nonSsLAuthBinding">
                <textMessageEncoding messageVersion="Soap11" />
                <nonSslAuthTransport authenticationScheme="None" allowCookies="true"  keepAliveEnabled="true" />
            </binding>
        </customBinding>
    </bindings>
</system.serviceModel>
</configuration>

无法访问受保护的WCF服务上的WSDL

当我查看PrincipalPermissionAttribute时,我在正确的轨道上。

由于我的误解,MSDN上的这篇文章让我相信这个属性只适用于windows组和windows主体。

然而,我在serviceAuthorization元素上发现了principalPermissionMode属性。根据MSDN:

principalPermissionMode

设置用于在服务器上执行操作的主体。取值包括:

  • 没有

  • UseWindowsGroups

  • UseAspNetRoles

  • 自定义

默认值是UseWindowsGroups。

所以最后我的解决方案是更新网页。配置如下:

从system.web删除了authorization元素。这段代码拒绝任何未经身份验证的用户访问。

<system.web>
...
    <authorization>
        <deny users="?" />
    </authorization>
...
</system.web>

我还必须修改我的serviceHostingEnvironment添加principalPermissionMode="Custom"。这将允许我使用我的自定义主体,而不是默认的windows组。

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true" httpGetUrl="WSDL" />
                <serviceAuthorization serviceAuthorizationManagerType="XXXX, XXXX" principalPermissionMode="Custom">
                    <authorizationPolicies>
                        <add policyType="XXXX, XXXX" />
                    </authorizationPolicies>
                </serviceAuthorization>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    ...
<system.serviceModel>

之后,我必须在我的服务方法中添加PrincipalPermissionAttribute,如下所示:

    [PrincipalPermission(SecurityAction.Demand, Authenticated=true, Unrestricted=true)]
    public string GetData(string data)
    {
        string primaryIdentity;
        if (ServiceSecurityContext.Current != null)
            primaryIdentity = ServiceSecurityContext.Current.PrimaryIdentity.Name;
        else
            primaryIdentity = "Not found";
        int cookies = 0;
        var request = HttpContext.Current.Request;
        if (request != null && request.Cookies.Count > 0)
            cookies = request.Cookies.Count;

        return string.Format("You passed in: {0} - Primary Identity of Authenticated User: {1} - Found {2} cookies", data, primaryIdentity, cookies);
    }

我现在可以在没有身份验证的情况下访问我的WSDL,但是拥有SSO票证的用户仍然可以调用我的web服务,而那些没有的用户则被拒绝。完美的工作。