我有一个ASP.NET MVC应用程序,它启用了Windows Identity Foundation身份验证,ADFS作为STS。该应用程序现在在.NET 4.5上使用MVC 4。当我将ASP.NET requestValidation从2.0更改为4.5时,我会得到以下错误:
A potentially dangerous Request.Form value was detected from the client
(wresult="<t:RequestSecurityTo...").
我想这是来自ADFS的重定向。我该怎么解决这个问题?
升级您的应用程序以使用框架中包含的WIF 4.5:http://msdn.microsoft.com/en-us/library/jj157089.aspx
将RequestValidation设置为4.5模式:
<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
WIF4.5可以很好地处理ASP.NET 4.5中的请求验证。
Eugenio引导我走向正确的方向。但他所指的示例在ASP.NET 4.5中已不起作用。正如我已经对他的回答所评论的那样,这导致了一种堆叠式的流动。这是因为请求验证现在是在请求数据时完成的。因此,验证是在WSFederationMessage.CreateFromFormPost请求数据时完成的。这会触发我们的请求验证器。此请求验证器再次调用WSFederationMessage.CreateFromFormPost,依此类推。在对WIF代码进行了一些挖掘之后,我现在有了一个经过轻微修改的requestvalidator,它正在工作。我们使用CreateFromNameValueCollection(CreateFromFormPost也使用它)而不是CreateFromFormPost,但现在我们可以用Request.Unvalided.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);
}
}
是的,这是从STS(ADFS)返回的SAML令牌。你可以按照Garrett的建议禁用验证,或者更好的是,你可以提供一个理解SAML令牌的合适的验证器,这很容易做到
请参阅其他问题/答案:WSFederationAuthenticationModule.IsSignInResponse 中的潜在危险请求表单
我们也遇到了同样的问题,但需要我们的验证器继续针对4.0构建,以便它可以在4.0或4.5环境中使用,因此我们无法使用Jaap发布的解决方案。我们的解决方案是在HttpContext.Items中删除一个标记,让我们知道验证已经在进行中,这样当触发嵌套验证时,我们就可以简单地让它通过。
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;
}
}
注意,在4.5请求验证模式下,如果您的asp.net服务器端代码在siginin期间(即发布SAML令牌时)使用request对象,您可能还有一些额外的工作要做。默认情况下,即使在4.5请求验证模式打开的情况下,发布SAML令牌时也会抛出Request.Params。