5

Mientras solucionar el problema descrito here, he creado otra que yo puedo encontrar en otro sitio en la red:WIF personalizada Solicitud Validador bucle infinito

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

El código anterior sigue llamando IsValidRequestString() lo que provoca un infinito lazo. La llamada es el mismo cada vez y la pila se ve así:

> 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] 

Esto está ocurriendo en una costumbre depender del servicio de token de seguridad del partido que federa la identidad de mi parte que confía en una ip creado por la herramienta FedUtil. ¿Alguien sabe por qué WSFederationMessage.CreateFromFormPost() llamaría al validador de solicitud? El resultado parece normal.

EDIT: Esto solo ocurre cuando ya he sido autenticado anteriormente. Si borro el caché de mi navegador, no sucede.

<?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> 
+0

Puede usted publicar el web.config? –

+0

Seguro, editado. Trabajé al respecto agregando una marca en el controlador que maneja la solicitud de inicio de sesión federado de los RP cuando el usuario ya está autenticado, y eso pareció solucionar el problema. Pero tengo curiosidad por saber qué estaba pasando. – ryanhallcs

+0

¿Cómo está protegiendo las acciones/controladores? ¿Está demandando [Autorizar]? –

Respuesta

0

En mi solicitud validador personalizado (juego en config):

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

Se trató de resolver el poste en un mensaje WIF y que llamó a la función de validación, lo que se agradece resultó en una ... desbordamiento de pila.

Remediar asegurando que los campos sean campos WIF.

2

El problema es que cuando un usuario se autentica, al acceder a System.HttpContext.Current.Request se activa el RequestValidator.

Así pasando una referencia System.HttpContext.Current.Request en WSFederationMessage.CreateFromFormPost dentro de la RequestValidator inicia el bucle infinito. No he investigado por qué ocurre este problema.

Si bien puede decidir no procesar solicitudes para usuarios ya autenticados en su STS (como lo hizo), eso no funciona si su código es un STS intermedio que depende de otro emisor. Por ejemplo, si el RP solicitante pasa un WHR diferente, aún desea reprocesar hasta su STS padre en caso de que el reino de origen diferente emita diferentes reclamos.

En mi caso, me vi obligado a modificar mi validador de solicitud simplemente devolviendo verdadero si hay un parámetro Wresult presente. Al hacerlo, la responsabilidad para validar el mensaje incomming se delega en el código que procesa las solicitudes de sesión a:

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); 
    } 
} 
2

El Technet originales wiki page ahora contiene la versión fija del código. La solución es omitir explícitamente la validación al obtener la recopilación de datos POST.

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

La clase Validation pertenece al conjunto de System.Web.WebPages.dll, que normalmente se instala junto con ASP.NET MVC.

Yo no quiero obligar a mi biblioteca de utilidades a MVC, así que busqué en la clase Validation con un decompilador y se utiliza un método de nivel más bajo desde el Microsoft.Web.Infrastructure.dll que ya había referenciado:

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; 
Cuestiones relacionadas