5

在解决此处描述的问题时,我创建了另一个我似乎可以在网络上其他任何地方找到的问题:

SignInResponseMessage message = WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage;

上面的代码不断调用 IsValidRequestString() 导致无限循环。每次调用都是相同的,堆栈如下所示:

>   TestIdentityBroker.dll!TestIdentityBroker.Service.WsFederationRequestValidator.IsValidRequestString(System.Web.HttpContext context, string value, System.Web.Util.RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) Line 19    C#
[External Code] 
TestIdentityBroker.dll!TestIdentityBroker.Service.WsFederationRequestValidator.IsValidRequestString(System.Web.HttpContext context, string value, System.Web.Util.RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) Line 19 + 0x21 bytes   C#
[External Code] 
TestIdentityBroker.dll!TestIdentityBroker.Service.WsFederationRequestValidator.IsValidRequestString(System.Web.HttpContext context, string value, System.Web.Util.RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) Line 19 + 0x21 bytes   C#
[External Code] 
TestIdentityBroker.dll!TestIdentityBroker.Service.WsFederationRequestValidator.IsValidRequestString(System.Web.HttpContext context, string value, System.Web.Util.RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex) Line 19 + 0x21 bytes   C#
[External Code] 

这发生在自定义信赖方安全令牌服务中,该服务将我的信赖方的身份与 FedUtil 工具创建的 ip 联合起来。有谁知道为什么WSFederationMessage.CreateFromFormPost()会调用请求验证器?返回的wreply似乎很正常。

编辑:这只发生在我之前已经过身份验证的情况下。如果我清除浏览器缓存,它不会发生。

<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->
<configuration>
  <configSections>
    <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <connectionStrings>
    <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="FederationMetadataLocation" value="X:\WebTest\TestIdentityBroker\TestIdentityBroker_STS\FederationMetadata\2007-06\FederationMetadata.xml" />
    <add key="SigningCertificateName" value="CN=Dev4"/>
  </appSettings>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <system.web>
    <!--<authorization>
      <deny users="?" />
    </authorization>-->
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <!--<authentication mode="Forms">
      <forms loginUrl="~/Federation/Authenticate" timeout="2880" />
    </authentication>-->
    <authentication mode="None" />
    <membership>
      <providers>
        <clear />
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <profile>
      <providers>
        <clear />
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
      </providers>
    </profile>
    <roleManager enabled="false">
      <providers>
        <clear />
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <httpRuntime requestValidationType="TestIdentityBroker.Service.WsFederationRequestValidator" />
    <httpModules>
      <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpModules>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
    </modules>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <microsoft.identityModel>
    <service>
      <audienceUris>
        <add value="https://rp_sts.local/" />
        <add value="https://rp_sts.local/Federation/LogOn" />
      </audienceUris>
      <federatedAuthentication>
        <wsFederation passiveRedirectEnabled="false" issuer="https://ip.local/" realm="https://rp_sts.local/" requireHttps="false" />
        <cookieHandler requireSsl="true" />
      </federatedAuthentication>
      <applicationService>
        <claimTypeRequired>
          <!--Following are the claims offered by STS 'http://ip.local/'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.-->
          <claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true" />
          <claimType type="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" optional="true" />
        </claimTypeRequired>
      </applicationService>
      <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <trustedIssuers>
          <add thumbprint="xx" name="https://ip.local/" />
        </trustedIssuers>
      </issuerNameRegistry>
    </service>
  </microsoft.identityModel>
</configuration>
4

3 回答 3

2

问题是,当用户通过身份验证时,访问System.HttpContext.Current.Request会触发 RequestValidator 被执行。

因此,将System.HttpContext.Current.Request引用传递给 RequestValidator 内的WSFederationMessage.CreateFromFormPost会启动无限循环。我还没有研究为什么会出现这个问题。

虽然您可以决定不处理已在您的 STS 上通过身份验证的用户的请求(如您所做的那样),但如果您的代码是依赖于另一个颁发者的中间 STS,则这不起作用。例如,如果请求的 RP 通过不同的 WHR,您仍然希望重新处理到您的父 STS,以防不同的主域发出不同的声明。

在我的情况下,如果存在 wresult 参数,我被迫通过简单地返回 true 来修改我的请求验证器。通过这样做,验证传入消息的责任被委托给处理登录请求的代码:

public class WIFRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        validationFailureIndex = 0;

        if (requestValidationSource == RequestValidationSource.Form && collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
        {
            return true;

            //SignInResponseMessage message = WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage;
            //if (message != null)
            //{
                //return true;
            //}
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}   
于 2012-07-14T21:39:40.743 回答
2

原始的 Technet wiki 页面现在包含固定版本的代码。解决方案是在获取 POST 数据的集合时显式跳过验证。

var unvalidatedFormValues = System.Web.Helpers.Validation.Unvalidated(context.Request).Form;
SignInResponseMessage message = WSFederationMessage.CreateFromNameValueCollection( WSFederationMessage.GetBaseUrl( context.Request.Url ), unvalidatedFormValues ) as SignInResponseMessage;

该类Validation属于System.Web.WebPages.dll程序集,通常与 ASP.NET MVC 一起安装。

我不想将我的实用程序库绑定到 MVC,所以我用反编译器查看了这个类,并使用了我已经引用过Validation的低级方法:Microsoft.Web.Infrastructure.dll

var baseUrl = WSFederationMessage.GetBaseUrl(context.Request.Url);
Func<NameValueCollection> formGetter, queryStringGetter;
Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.GetUnvalidatedCollections(context, out formGetter, out queryStringGetter);
if (WSFederationMessage.CreateFromNameValueCollection(baseUrl, formGetter()) is SignInResponseMessage)
    return true;
于 2013-11-18T14:56:31.877 回答
0

在我的自定义请求验证器(在配置中设置):

<httpRuntime requestValidationType="TestIdentityBroker.Service.WsFederationRequestValidator" />

它试图将帖子解析为 WIF 消息并调用验证功能,这导致...堆栈溢出。

通过确保字段是 WIF 字段进行补救。

于 2012-03-06T17:46:03.837 回答