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

时间:2014-06-24 16:37:46

标签: c# wcf wsdl authorization jasig

我已经设置了一个在ASP.NET兼容模式下运行的WCF服务,这样我就可以利用我网站其余部分使用的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主体使用自定义主体这可能不行。

请注意,如果我从web.config中删除授权标记,我再次可以访问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>

1 个答案:

答案 0 :(得分:0)

我在查看PrincipalPermissionAttribute之前,我在正确的轨道上。

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

但是我在serviceAuthorization element上发现了principalPermissionMode属性。根据MSDN:

principalPermissionMode

  

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

     
      
  •   
  • UseWindowsGroups

  •   
  • UseAspNetRoles

  •   
  • 定制

  •   
     

默认值为UseWindowsGroups。

所以最后我的解决方案是更新web.config,如下所示:

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

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

我还必须通过添加principalPermissionMode =&#34; Custom&#34;来修改我的serviceHostingEnvironment。这将允许我使用我的自定义主体而不是默认的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服务,而那些不会被拒绝的用户。效果很好。

相关问题