ASP.NET requestValidation 4.5 and WIF

2019-04-09 15:52发布

I have an ASP.NET MVC application with Windows Identity Foundation authentication enabled with ADFS as STS. The application is now on .NET 4.5 with MVC 4. When I change the ASP.NET requestValidation from 2.0 to 4.5, I get this error:

A potentially dangerous Request.Form value was detected from the client 
(wresult="<t:RequestSecurityTo...").

I guess this is the redirect from ADFS. How can I fix this?

标签: asp.net wif
5条回答
女痞
2楼-- · 2019-04-09 16:15

Upgrade your application to use WIF 4.5 included in the framework: http://msdn.microsoft.com/en-us/library/jj157089.aspx

Set RequestValidation to 4.5 mode:

<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />

WIF 4.5 plays nicely with the request validation in ASP.NET 4.5.

查看更多
混吃等死
3楼-- · 2019-04-09 16:18

Note, with 4.5 request validation mode you may still have some additional work to do if your asp.net server side code uses the Request object during siginin (i.e. when SAML token is posted). By default, use of Request.Params will throw when SAML token is posted even with 4.5 request validation mode turned on.

查看更多
不美不萌又怎样
4楼-- · 2019-04-09 16:30

Eugenio guided me to the right direction. But the sample he is refering to is not working anymore in ASP.NET 4.5. As I already commented on his answer, it is resulting in a stackoverflow. This is because requestvalidation is now done when data is requested. So the validation is done when WSFederationMessage.CreateFromFormPost requests the data. This triggers our requestvalidator. And this requestvalidator calls WSFederationMessage.CreateFromFormPost again and so on. After some digging in the WIF code, I have now a slightly modified requestvalidator which is working. Instead of CreateFromFormPost we use CreateFromNameValueCollection (which is also used by CreateFromFormPost), but now we can feed it with Request.Unvalidated.Form.

public class RequestValidator : System.Web.Util.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))
        {
            if (WSFederationMessage.CreateFromNameValueCollection(WSFederationMessage.GetBaseUrl(context.Request.Url), context.Request.Unvalidated.Form) as SignInResponseMessage != null)
            {
                return true;
            }
        }
        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
查看更多
Root(大扎)
5楼-- · 2019-04-09 16:30

We had the same problem, but needed for our validator to continue to be built against 4.0 so that it can be used in either 4.0 or 4.5 environments so we couldn't use the solution that Jaap posted. Our solution was to drop a marker in HttpContext.Items to let us know that a validation is already in progress so that when the nested validation is triggered we can simply let it pass through.


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))
        {
            if(AlreadyValidating(context))
            {
                return true; // Allows us to bypass check that happens as a result of trying to use context.Request.Form
            }

            StartValidating(context);
            if (IsWsFedSigninResponse(context))
            {
                return true;
            }
            EndValidating(context);
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }

    private static bool AlreadyValidating(HttpContext context)
    {
        return context.Items["__ApprendaRequestValidatorInProgress"] != null;
    }

    private static void StartValidating(HttpContext context)
    {
        context.Items["__ApprendaRequestValidatorInProgress"] = new object();
    }

    private static bool IsWsFedSigninResponse(HttpContext context)
    {
        return WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage != null;
    }

    private static void EndValidating(HttpContext context)
    {
        context.Items["__ApprendaRequestValidatorInProgress"] = null;
    }
}
查看更多
smile是对你的礼貌
6楼-- · 2019-04-09 16:39

Yes, this is the SAML token posted back from the STS (ADFS) in your case. You can disable validation as Garrett suggests or better yet, you can supply a proper validator that understands SAML tokens, which is very easy to do.

See this other question/answer: Potentially dangerous Request.Form in WSFederationAuthenticationModule.IsSignInResponse

查看更多
登录 后发表回答