Add Antiforgery to the FormTagHelper pre-check for processing.

- Added a test case to the HtmlGeneration functional test (the one verifying complex FormTagHelpers).
- Added unit test verifying antiforgery behavior when it's the only provided parameter.

#6006
This commit is contained in:
N. Taylor Mullen 2017-04-24 21:45:11 -07:00
parent 5c8a161ace
commit ef0333ac6a
4 changed files with 66 additions and 2 deletions

View File

@ -242,7 +242,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
TagBuilder tagBuilder = null;
if (Action == null && Controller == null && Route == null && _routeValues == null && Fragment == null && Area == null && Page == null)
if (Action == null &&
Controller == null &&
Route == null &&
_routeValues == null &&
Fragment == null &&
Area == null &&
Page == null &&
// Antiforgery will sometime be set globally via TagHelper Initializers, verify it was provided in the cshtml.
!context.AllAttributes.ContainsName(AntiforgeryAttributeName))
{
// Empty form tag such as <form></form>. Let it flow to the output as-is and only handle anti-forgery.
}

View File

@ -1,4 +1,4 @@
<html>
<html>
<head>
<meta charset="utf-8" />
<title>Form</title>
@ -8,6 +8,7 @@
<h2>Form Tag Helper Test</h2>
<form></form>
<form action="/HtmlGeneration_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
<form action="/HtmlGeneration_Home/Form" method="post"></form>
<form action="/HtmlGeneration_Home/Form" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
<form action="/HtmlGeneration_Home/Form" method="post"></form>

View File

@ -25,6 +25,60 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
public class FormTagHelperTest
{
[Fact]
public async Task ProcessAsync_AspAntiforgeryAloneGeneratesProperFormTag()
{
// Arrange
var expectedTagName = "form";
var metadataProvider = new TestModelMetadataProvider();
var tagHelperContext = new TagHelperContext(
tagName: "form",
allAttributes: new TagHelperAttributeList()
{
{ "asp-antiforgery", true }
},
items: new Dictionary<object, object>(),
uniqueId: "test");
var output = new TagHelperOutput(
expectedTagName,
attributes: new TagHelperAttributeList(),
getChildContentAsync: (useCachedResult, encoder) =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("Something");
return Task.FromResult<TagHelperContent>(tagHelperContent);
});
var urlHelper = new Mock<IUrlHelper>();
var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object);
var viewContext = TestableHtmlGenerator.GetViewContext(
model: null,
htmlGenerator: htmlGenerator,
metadataProvider: metadataProvider);
viewContext.HttpContext.Request.Path = "/home/index";
var expectedPostContent = HtmlContentUtilities.HtmlContentToString(
htmlGenerator.GenerateAntiforgery(viewContext),
HtmlEncoder.Default);
var formTagHelper = new FormTagHelper(htmlGenerator)
{
ViewContext = viewContext,
Antiforgery = true,
};
// Act
await formTagHelper.ProcessAsync(tagHelperContext, output);
// Assert
Assert.Equal(2, output.Attributes.Count);
var attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("method"));
Assert.Equal("post", attribute.Value);
attribute = Assert.Single(output.Attributes, attr => attr.Name.Equals("action"));
Assert.Equal("/home/index", attribute.Value);
Assert.Empty(output.PreContent.GetContent());
Assert.True(output.Content.GetContent().Length == 0);
Assert.Equal(expectedPostContent, output.PostContent.GetContent());
Assert.Equal(expectedTagName, output.TagName);
}
[Fact]
public async Task ProcessAsync_EmptyHtmlStringActionGeneratesAntiforgery()
{

View File

@ -11,6 +11,7 @@
<h2>Form Tag Helper Test</h2>
<form></form>
<form asp-antiforgery="true"></form>
<form asp-controller="HtmlGeneration_Home" asp-action="Form"></form>
<form asp-controller="HtmlGeneration_Home" asp-action="Form" asp-antiforgery="true"></form>
<form asp-controller="HtmlGeneration_Home" asp-action="Form" asp-antiforgery="false"></form>