Skip to content

Commit 2b7ac74

Browse files
committed
Do not use FormattedModelValue in password editor template
- #135 - see also PR aspnet/Mvc#7430 - add quirk switch to reverse this if necessary
1 parent f9e06d6 commit 2b7ac74

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

src/System.Web.Mvc/Html/DefaultEditorTemplates.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Globalization;
1010
using System.Linq;
1111
using System.Text;
12+
using System.Web.Configuration;
1213
using System.Web.Mvc.Properties;
1314
using System.Web.Routing;
1415
using System.Web.UI.WebControls;
@@ -18,6 +19,7 @@ namespace System.Web.Mvc.Html
1819
internal static class DefaultEditorTemplates
1920
{
2021
private const string HtmlAttributeKey = "htmlAttributes";
22+
private const string UsePasswordValue = "Switch.System.Web.Mvc.UsePasswordValue";
2123

2224
internal static string BooleanTemplate(HtmlHelper html)
2325
{
@@ -149,11 +151,11 @@ internal static string HiddenInputTemplate(HtmlHelper html)
149151

150152
MvcHtmlString hiddenResult;
151153

152-
if (htmlAttributesDict != null)
154+
if (htmlAttributesDict != null)
153155
{
154156
hiddenResult = html.Hidden(String.Empty, model, htmlAttributesDict);
155-
}
156-
else
157+
}
158+
else
157159
{
158160
hiddenResult = html.Hidden(String.Empty, model, htmlAttributesObject);
159161
}
@@ -178,9 +180,9 @@ private static IDictionary<string, object> CreateHtmlAttributes(HtmlHelper html,
178180
{
179181
return MergeHtmlAttributes(htmlAttributesObject, className, inputType);
180182
}
181-
183+
182184
var htmlAttributes = new Dictionary<string, object>()
183-
{
185+
{
184186
{ "class", className }
185187
};
186188
if (inputType != null)
@@ -274,9 +276,21 @@ internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateH
274276

275277
internal static string PasswordTemplate(HtmlHelper html)
276278
{
277-
return html.Password(String.Empty,
278-
html.ViewContext.ViewData.TemplateInfo.FormattedModelValue,
279-
CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString();
279+
object value = null;
280+
var usePasswordStrings = WebConfigurationManager.AppSettings.GetValues(UsePasswordValue);
281+
bool usePasswordValue;
282+
if (usePasswordStrings != null &&
283+
usePasswordStrings.Length > 0 &&
284+
bool.TryParse(usePasswordStrings[0], out usePasswordValue) &&
285+
usePasswordValue)
286+
{
287+
value = html.ViewContext.ViewData.TemplateInfo.FormattedModelValue;
288+
}
289+
290+
return html.Password(
291+
name: String.Empty,
292+
value: value,
293+
htmlAttributes: CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString();
280294
}
281295

282296
private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)

test/System.Web.Mvc.Test/Html/Test/DefaultEditorTemplatesTest.cs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -731,14 +731,63 @@ public void ObjectTemplateDisplaysSimpleDisplayTextWithNonNullModelTemplateDepth
731731
public void PasswordTemplateTests()
732732
{
733733
Assert.Equal(
734-
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />",
734+
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />",
735735
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper<string>("Value")));
736736

737737
Assert.Equal(
738-
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"&lt;script>alert(&#39;XSS!&#39;)&lt;/script>\" />",
738+
"<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />",
739739
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper<string>("<script>alert('XSS!')</script>")));
740740
}
741741

742+
[Fact]
743+
public void PasswordTemplate_ReturnsInputElement_IgnoresValues()
744+
{
745+
// Arrange
746+
var expected = "<input class=\"text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" " +
747+
"type=\"password\" />";
748+
749+
// Template ignores Model and FormattedModelValue.
750+
var helper = MakeHtmlHelper<string>(model: "Model string", formattedModelValue: "Formatted string");
751+
752+
var viewData = helper.ViewData;
753+
var templateInfo = viewData.TemplateInfo;
754+
templateInfo.HtmlFieldPrefix = "FieldPrefix";
755+
756+
// Template ignores ModelState and ViewData.
757+
var valueProviderResult = new ValueProviderResult(
758+
"Raw model string",
759+
"Attempted model string",
760+
CultureInfo.InvariantCulture);
761+
viewData.ModelState.SetModelValue("FieldPrefix", valueProviderResult);
762+
viewData["FieldPrefix"] = "ViewData string";
763+
764+
// Act
765+
var result = DefaultEditorTemplates.PasswordTemplate(helper);
766+
767+
// Assert
768+
Assert.Equal(expected, result);
769+
}
770+
771+
[Fact]
772+
public void PasswordTemplate_ReturnsInputElement_UsesHtmlAttributes()
773+
{
774+
// Arrange
775+
var expected = "<input class=\"super text-box single-line password\" id=\"FieldPrefix\" " +
776+
"name=\"FieldPrefix\" type=\"password\" value=\"Html attributes string\" />";
777+
var helper = MakeHtmlHelper<string>(model: null);
778+
var viewData = helper.ViewData;
779+
var templateInfo = viewData.TemplateInfo;
780+
templateInfo.HtmlFieldPrefix = "FieldPrefix";
781+
782+
viewData["htmlAttributes"] = new { @class = "super", value = "Html attributes string" };
783+
784+
// Act
785+
var result = DefaultEditorTemplates.PasswordTemplate(helper);
786+
787+
// Assert
788+
Assert.Equal(expected, result);
789+
}
790+
742791
public static TheoryDataSet<object, string> PasswordTemplateHtmlAttributeData
743792
{
744793
get
@@ -747,11 +796,11 @@ public static TheoryDataSet<object, string> PasswordTemplateHtmlAttributeData
747796
{
748797
{
749798
new { @class = "form-control" },
750-
"<input class=\"form-control text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />"
799+
"<input class=\"form-control text-box single-line password\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />"
751800
},
752801
{
753802
new { @class = "form-control", custom = "foo" },
754-
"<input class=\"form-control text-box single-line password\" custom=\"foo\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" value=\"Value\" />"
803+
"<input class=\"form-control text-box single-line password\" custom=\"foo\" id=\"FieldPrefix\" name=\"FieldPrefix\" type=\"password\" />"
755804
}
756805
};
757806
}

0 commit comments

Comments
 (0)