Added support for ignoring integrity attribute on fallback for the Link TagHelper

- Do not include integrity attribute when asp-fallback-intergrity-check is false
 - Added Unit Tests, manual tests

Addresses #7845
This commit is contained in:
jmhmaine 2018-06-05 09:34:15 -04:00 committed by N. Taylor Mullen
parent 4f7e849cc1
commit 8a77ed23d3
13 changed files with 226 additions and 14 deletions

View File

@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("link", Attributes = HrefIncludeAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = HrefIncludeAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = HrefExcludeAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = HrefExcludeAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = FallbackHrefAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = FallbackHrefAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = FallbackHrefIntegrityCheckAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = FallbackHrefIncludeAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = FallbackHrefIncludeAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = FallbackHrefExcludeAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = FallbackHrefExcludeAttributeName, TagStructure = TagStructure.WithoutEndTag)]
[HtmlTargetElement("link", Attributes = FallbackTestClassAttributeName, TagStructure = TagStructure.WithoutEndTag)] [HtmlTargetElement("link", Attributes = FallbackTestClassAttributeName, TagStructure = TagStructure.WithoutEndTag)]
@ -40,6 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string HrefIncludeAttributeName = "asp-href-include"; private const string HrefIncludeAttributeName = "asp-href-include";
private const string HrefExcludeAttributeName = "asp-href-exclude"; private const string HrefExcludeAttributeName = "asp-href-exclude";
private const string FallbackHrefAttributeName = "asp-fallback-href"; private const string FallbackHrefAttributeName = "asp-fallback-href";
private const string FallbackHrefIntegrityCheckAttributeName = "asp-fallback-href-integrity-check";
private const string FallbackHrefIncludeAttributeName = "asp-fallback-href-include"; private const string FallbackHrefIncludeAttributeName = "asp-fallback-href-include";
private const string FallbackHrefExcludeAttributeName = "asp-fallback-href-exclude"; private const string FallbackHrefExcludeAttributeName = "asp-fallback-href-exclude";
private const string FallbackTestClassAttributeName = "asp-fallback-test-class"; private const string FallbackTestClassAttributeName = "asp-fallback-test-class";
@ -147,6 +149,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(FallbackHrefAttributeName)] [HtmlAttributeName(FallbackHrefAttributeName)]
public string FallbackHref { get; set; } public string FallbackHref { get; set; }
/// <summary>
/// Boolean value that determines if Integrity Hash will be compared with <see cref="FallbackHref"/> value.
/// Value defaults to true if not provided.
/// Must be used in conjunction with <see cref="FallbackHref"/>.
/// </summary>
[HtmlAttributeName(FallbackHrefIntegrityCheckAttributeName)]
public bool? FallbackHrefIntegrityCheck { get; set; }
/// <summary> /// <summary>
/// Value indicating if file version should be appended to the href urls. /// Value indicating if file version should be appended to the href urls.
/// </summary> /// </summary>
@ -367,6 +377,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
continue; continue;
} }
// do not write integrity attribute when FallbackHrefIntegrityCheck is false
if (attribute.Name.Equals("integrity", StringComparison.OrdinalIgnoreCase) && FallbackHrefIntegrityCheck == false)
{
continue;
}
attribute.WriteTo(StringWriter, HtmlEncoder); attribute.WriteTo(StringWriter, HtmlEncoder);
StringWriter.Write(' '); StringWriter.Write(' ');
} }

View File

@ -27,6 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("script", Attributes = FallbackSrcIncludeAttributeName)] [HtmlTargetElement("script", Attributes = FallbackSrcIncludeAttributeName)]
[HtmlTargetElement("script", Attributes = FallbackSrcExcludeAttributeName)] [HtmlTargetElement("script", Attributes = FallbackSrcExcludeAttributeName)]
[HtmlTargetElement("script", Attributes = FallbackTestExpressionAttributeName)] [HtmlTargetElement("script", Attributes = FallbackTestExpressionAttributeName)]
[HtmlTargetElement("script", Attributes = FallbackIntegrityCheckAttributeName)]
[HtmlTargetElement("script", Attributes = AppendVersionAttributeName)] [HtmlTargetElement("script", Attributes = AppendVersionAttributeName)]
public class ScriptTagHelper : UrlResolutionTagHelper public class ScriptTagHelper : UrlResolutionTagHelper
{ {
@ -34,6 +35,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
private const string SrcExcludeAttributeName = "asp-src-exclude"; private const string SrcExcludeAttributeName = "asp-src-exclude";
private const string FallbackSrcAttributeName = "asp-fallback-src"; private const string FallbackSrcAttributeName = "asp-fallback-src";
private const string FallbackSrcIncludeAttributeName = "asp-fallback-src-include"; private const string FallbackSrcIncludeAttributeName = "asp-fallback-src-include";
private const string FallbackIntegrityCheckAttributeName = "asp-fallback-integrity-check";
private const string FallbackSrcExcludeAttributeName = "asp-fallback-src-exclude"; private const string FallbackSrcExcludeAttributeName = "asp-fallback-src-exclude";
private const string FallbackTestExpressionAttributeName = "asp-fallback-test"; private const string FallbackTestExpressionAttributeName = "asp-fallback-test";
private const string SrcAttributeName = "src"; private const string SrcAttributeName = "src";
@ -129,6 +131,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(FallbackSrcAttributeName)] [HtmlAttributeName(FallbackSrcAttributeName)]
public string FallbackSrc { get; set; } public string FallbackSrc { get; set; }
/// <summary>
/// Boolean value that determines if Integrity Hash will be compared with <see cref="FallbackSrc"/> value.
/// Value defaults to true if not provided.
/// Must be used in conjunction with <see cref="FallbackSrc"/>.
/// </summary>
[HtmlAttributeName(FallbackIntegrityCheckAttributeName)]
public bool? FallbackIntegrityCheck { get; set; }
/// <summary> /// <summary>
/// Value indicating if file version should be appended to src urls. /// Value indicating if file version should be appended to src urls.
/// </summary> /// </summary>
@ -312,6 +322,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var attribute = attributes[i]; var attribute = attributes[i];
if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase)) if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
{ {
// do not write integrity attribute when fallbackintegrityCheck is false
if (attribute.Name.Equals("integrity", StringComparison.OrdinalIgnoreCase) && FallbackIntegrityCheck == false) continue;
StringWriter.Write(' '); StringWriter.Write(' ');
attribute.WriteTo(StringWriter, HtmlEncoder); attribute.WriteTo(StringWriter, HtmlEncoder);
} }

View File

@ -19,11 +19,27 @@
// Fallback to globbed src // Fallback to globbed src
</script> </script>
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]" title='"the" title'></script>]]"));</script> <script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]" title='"the" title'></script>]]"));</script>
<script src="HtmlEncode[[/styles/siteIntegrity.js?a=integrity]]" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script loading primary source, applied integrity hash to primary source.
</script>
<script>(true||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/sub/site2.js?a=integrity]]" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ="></script>]]"));</script>
<script src="HtmlEncode[[/styles/siteIntegrity.js?a=integrity]]" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, applies integrity hash to fallback.
</script>
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/sub/siteIntegrity2.js?a=integrity]]" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ="></script>]]"));</script>
<script src="HtmlEncode[[/styles/siteIntegrity.js?a=integrity]]" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, ignores integrity hash on fallback.
</script>
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/sub/siteIntegrity3.js?a=integrity]]" crossorigin="anonymous"></script>]]"));</script>
<script src="HtmlEncode[[/blank.js]]"> <script src="HtmlEncode[[/blank.js]]">
// Fallback to globbed src with exclude // Fallback to globbed src with exclude
</script> </script>
<script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script>]]"));</script> <script>(false||document.write("JavaScriptEncode[[<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/siteIntegrity.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity2.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity3.js]]"></script>]]"));</script>
<script src="HtmlEncode[[/blank.js]]"> <script src="HtmlEncode[[/blank.js]]">
// Fallback to globbed and static src // Fallback to globbed and static src
@ -65,7 +81,7 @@
<script src="HtmlEncode[[/styles/site.js]]"></script> <script src="HtmlEncode[[/styles/site.js]]"></script>
<!-- Globbed script tag with existing file and exclude --> <!-- Globbed script tag with existing file and exclude -->
<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script> <script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/siteIntegrity.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity2.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity3.js]]"></script>
<script> <script>
// Globbed script tag missing include // Globbed script tag missing include
@ -76,7 +92,7 @@
</script> </script>
<!-- Globbed script tag with comma separated include pattern --> <!-- Globbed script tag with comma separated include pattern -->
<script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script><script src="HtmlEncode[[/styles/sub/site3.js]]"></script> <script src="HtmlEncode[[/styles/site.js]]"></script><script src="HtmlEncode[[/styles/siteIntegrity.js]]"></script><script src="HtmlEncode[[/styles/sub/site2.js]]"></script><script src="HtmlEncode[[/styles/sub/site3.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity2.js]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity3.js]]"></script>
<!-- Globbed script tag with missing file --> <!-- Globbed script tag with missing file -->
@ -110,9 +126,9 @@
</script> </script>
<!-- Globbed script tag with existing files and version --> <!-- Globbed script tag with existing files and version -->
<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script><script src="HtmlEncode[[/styles/sub/site3.js?v=lmeAMiqm76lnGyqHhu6PIBHAC0Vt46mgVB_KaG_gGdA]]"></script> <script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/styles/siteIntegrity.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ]]"></script><script src="HtmlEncode[[/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script><script src="HtmlEncode[[/styles/sub/site3.js?v=lmeAMiqm76lnGyqHhu6PIBHAC0Vt46mgVB_KaG_gGdA]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity2.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity3.js?v=6I1ncApSzTYytACF7244bg3a_sEnKrGH8nVudoaN984]]"></script>
<!-- Globbed script tag with existing file, exclude and version --> <!-- Globbed script tag with existing file, exclude and version -->
<script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script> <script src="HtmlEncode[[/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I]]"></script><script src="HtmlEncode[[/styles/siteIntegrity.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ]]"></script><script src="HtmlEncode[[/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity2.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ]]"></script><script src="HtmlEncode[[/styles/sub/siteIntegrity3.js?v=6I1ncApSzTYytACF7244bg3a_sEnKrGH8nVudoaN984]]"></script>
</body> </body>
</html> </html>

View File

@ -19,11 +19,27 @@
// Fallback to globbed src // Fallback to globbed src
</script> </script>
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022 title=\u0027\u0022the\u0022 title\u0027\u003E\u003C\/script\u003E"));</script> <script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022 title=\u0027\u0022the\u0022 title\u0027\u003E\u003C\/script\u003E"));</script>
<script src="/styles/siteIntegrity.js?a=integrity" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script loading primary source, applied integrity hash to primary source.
</script>
<script>(true||document.write("\u003Cscript src=\u0022\/styles\/sub\/site2.js?a=integrity\u0022 crossorigin=\u0022anonymous\u0022 integrity=\u0022sha256-tMQLOHBNPE829MHQPO8metegsGobA\/henDPOvtZOWhQ=\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/styles/siteIntegrity.js?a=integrity" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, applies integrity hash to fallback.
</script>
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/sub\/siteIntegrity2.js?a=integrity\u0022 crossorigin=\u0022anonymous\u0022 integrity=\u0022sha256-tMQLOHBNPE829MHQPO8metegsGobA\/henDPOvtZOWhQ=\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/styles/siteIntegrity.js?a=integrity" crossorigin="anonymous" integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, ignores integrity hash on fallback.
</script>
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/sub\/siteIntegrity3.js?a=integrity\u0022 crossorigin=\u0022anonymous\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/blank.js"> <script src="/blank.js">
// Fallback to globbed src with exclude // Fallback to globbed src with exclude
</script> </script>
<script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/site2.js\u0022\u003E\u003C\/script\u003E"));</script> <script>(false||document.write("\u003Cscript src=\u0022\/styles\/site.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/siteIntegrity.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/site2.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/siteIntegrity2.js\u0022\u003E\u003C\/script\u003E\u003Cscript src=\u0022\/styles\/sub\/siteIntegrity3.js\u0022\u003E\u003C\/script\u003E"));</script>
<script src="/blank.js"> <script src="/blank.js">
// Fallback to globbed and static src // Fallback to globbed and static src
@ -65,7 +81,7 @@
<script src="/styles/site.js"></script> <script src="/styles/site.js"></script>
<!-- Globbed script tag with existing file and exclude --> <!-- Globbed script tag with existing file and exclude -->
<script src="/styles/site.js"></script><script src="/styles/sub/site2.js"></script> <script src="/styles/site.js"></script><script src="/styles/siteIntegrity.js"></script><script src="/styles/sub/site2.js"></script><script src="/styles/sub/siteIntegrity2.js"></script><script src="/styles/sub/siteIntegrity3.js"></script>
<script> <script>
// Globbed script tag missing include // Globbed script tag missing include
@ -76,7 +92,7 @@
</script> </script>
<!-- Globbed script tag with comma separated include pattern --> <!-- Globbed script tag with comma separated include pattern -->
<script src="/styles/site.js"></script><script src="/styles/sub/site2.js"></script><script src="/styles/sub/site3.js"></script> <script src="/styles/site.js"></script><script src="/styles/siteIntegrity.js"></script><script src="/styles/sub/site2.js"></script><script src="/styles/sub/site3.js"></script><script src="/styles/sub/siteIntegrity2.js"></script><script src="/styles/sub/siteIntegrity3.js"></script>
<!-- Globbed script tag with missing file --> <!-- Globbed script tag with missing file -->
@ -110,9 +126,9 @@
</script> </script>
<!-- Globbed script tag with existing files and version --> <!-- Globbed script tag with existing files and version -->
<script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I"></script><script src="/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0"></script><script src="/styles/sub/site3.js?v=lmeAMiqm76lnGyqHhu6PIBHAC0Vt46mgVB_KaG_gGdA"></script> <script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I"></script><script src="/styles/siteIntegrity.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ"></script><script src="/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0"></script><script src="/styles/sub/site3.js?v=lmeAMiqm76lnGyqHhu6PIBHAC0Vt46mgVB_KaG_gGdA"></script><script src="/styles/sub/siteIntegrity2.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ"></script><script src="/styles/sub/siteIntegrity3.js?v=6I1ncApSzTYytACF7244bg3a_sEnKrGH8nVudoaN984"></script>
<!-- Globbed script tag with existing file, exclude and version --> <!-- Globbed script tag with existing file, exclude and version -->
<script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I"></script><script src="/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0"></script> <script src="/styles/site.js?v=jx1PJjLX32-xgQQx2BxnckU9QH9DVKkm4-M5bSK869I"></script><script src="/styles/siteIntegrity.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ"></script><script src="/styles/sub/site2.js?v=pwJaxaQxnb-rPAdF2JlAp4xiPNq1XuJFd6TyOOfNF-0"></script><script src="/styles/sub/siteIntegrity2.js?v=tMQLOHBNPE829MHQPO8metegsGobA_henDPOvtZOWhQ"></script><script src="/styles/sub/siteIntegrity3.js?v=6I1ncApSzTYytACF7244bg3a_sEnKrGH8nVudoaN984"></script>
</body> </body>
</html> </html>

View File

@ -3,5 +3,4 @@
<form method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form> <form method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
<form action="" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form> <form action="" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
<form action="/Foo/Bar/Baz.html" method="get"></form> <form action="/Foo/Bar/Baz.html" method="get"></form>
<form action="/Foo/Bar/Baz.html" method="post"></form> <form action="/Foo/Bar/Baz.html" method="post"></form>
<form action="/RedirectToPage" method="post"><input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>

View File

@ -263,7 +263,49 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
tagHelper.FallbackTestValue = "hidden"; tagHelper.FallbackTestValue = "hidden";
tagHelper.AppendVersion = true; tagHelper.AppendVersion = true;
} }
} },
// asp-fallback-href-integrity-check Attribute true
{
new TagHelperAttributeList
{
new TagHelperAttribute("asp-fallback-href", "test.css"),
new TagHelperAttribute("asp-fallback-test-class", "hidden"),
new TagHelperAttribute("asp-fallback-test-property", "visibility"),
new TagHelperAttribute("asp-fallback-test-value", "hidden"),
new TagHelperAttribute("asp-append-version", "true"),
new TagHelperAttribute("asp-fallback-href-integrity-check", "true")
},
tagHelper =>
{
tagHelper.FallbackHref = "test.css";
tagHelper.FallbackTestClass = "hidden";
tagHelper.FallbackTestProperty = "visibility";
tagHelper.FallbackTestValue = "hidden";
tagHelper.AppendVersion = true;
tagHelper.FallbackHrefIntegrityCheck = true;
}
},
// asp-fallback-href-integrity-check Attribute false
{
new TagHelperAttributeList
{
new TagHelperAttribute("asp-fallback-href", "test.css"),
new TagHelperAttribute("asp-fallback-test-class", "hidden"),
new TagHelperAttribute("asp-fallback-test-property", "visibility"),
new TagHelperAttribute("asp-fallback-test-value", "hidden"),
new TagHelperAttribute("asp-append-version", "true"),
new TagHelperAttribute("asp-fallback-href-integrity-check", "false")
},
tagHelper =>
{
tagHelper.FallbackHref = "test.css";
tagHelper.FallbackTestClass = "hidden";
tagHelper.FallbackTestProperty = "visibility";
tagHelper.FallbackTestValue = "hidden";
tagHelper.AppendVersion = true;
tagHelper.FallbackHrefIntegrityCheck = false;
}
},
}; };
} }
} }

View File

@ -156,6 +156,20 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
tagHelper.FallbackTestExpression = "isavailable()"; tagHelper.FallbackTestExpression = "isavailable()";
} }
}, },
{
new TagHelperAttributeList
{
new TagHelperAttribute("asp-fallback-src", "test.js"),
new TagHelperAttribute("asp-fallback-test", "isavailable()"),
new TagHelperAttribute("asp-fallback-integrity-check", "false")
},
tagHelper =>
{
tagHelper.FallbackSrc = "test.js";
tagHelper.FallbackTestExpression = "isavailable()";
tagHelper.FallbackIntegrityCheck = false;
}
},
{ {
new TagHelperAttributeList new TagHelperAttributeList
{ {
@ -182,6 +196,22 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
tagHelper.FallbackTestExpression = "isavailable()"; tagHelper.FallbackTestExpression = "isavailable()";
} }
}, },
{
new TagHelperAttributeList
{
new TagHelperAttribute("asp-fallback-src", "test.js"),
new TagHelperAttribute("asp-fallback-src-include", "*.js"),
new TagHelperAttribute("asp-fallback-test", "isavailable()"),
new TagHelperAttribute("asp-fallback-integrity-check", "false")
},
tagHelper =>
{
tagHelper.FallbackSrc = "test.js";
tagHelper.FallbackSrcInclude = "*.css";
tagHelper.FallbackTestExpression = "isavailable()";
tagHelper.FallbackIntegrityCheck = false;
}
},
{ {
new TagHelperAttributeList new TagHelperAttributeList
{ {

View File

@ -46,6 +46,35 @@
asp-fallback-test-property="visibility" asp-fallback-test-property="visibility"
asp-fallback-test-value="hidden" /> asp-fallback-test-value="hidden" />
<!-- Fallback to static href with no asp-fallback-href-integrity-check attribute, default behavior is to keep integrity hash -->
<link href="~/styles/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title='"the" title'
integrity="XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh+pQc="
crossorigin="anonymous"
asp-fallback-href="~/styles/site.css?a=b&c=d"
asp-fallback-test-class="hidden"
asp-fallback-test-property="visibility"
asp-fallback-test-value="hidden" />
<!-- Fallback to static href with asp-fallback-href-integrity-check set to true, default behavior is to keep integrity hash -->
<link href="~/styles/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title='"the" title'
integrity="XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh+pQc="
crossorigin="anonymous"
asp-fallback-href="~/styles/site.css?a=b&c=d"
asp-fallback-test-class="hidden"
asp-fallback-test-property="visibility"
asp-fallback-test-value="hidden"
asp-fallback-href-integrity-check="true" />
<!-- Fallback to static href with asp-fallback-href-integrity-check set to false, removes integrity attribute on fallback so that different CSS can be loaded -->
<link href="~/styles/site.min.css?a=b&c=d" rel="stylesheet" data-extra="test" title='"the" title'
integrity="XY7YsMemPf8AGU4SIX9ED9eOjK1LOQWu2dmCNmh+pQc="
crossorigin="anonymous"
asp-fallback-href="~/styles/siteIntegrity.css?a=b&c=d"
asp-fallback-test-class="hidden"
asp-fallback-test-property="visibility"
asp-fallback-test-value="hidden"
asp-fallback-href-integrity-check="false" />
<!-- Fallback to static href with dynamic attributes --> <!-- Fallback to static href with dynamic attributes -->
<link href="~/styles/site.min.css?a=b&c=d" rel="@("stylesheet")" data-extra="@("test")" title='@(@"""the"" title")' <link href="~/styles/site.min.css?a=b&c=d" rel="@("stylesheet")" data-extra="@("test")" title='@(@"""the"" title")'
asp-fallback-href="~/styles/site.css?a=b&c=d" asp-fallback-href="~/styles/site.css?a=b&c=d"

View File

@ -1,4 +1,4 @@
@* @*
Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
*@ *@
@ -22,6 +22,33 @@
<script src="~/blank.js" asp-fallback-src-include="**/site.js" asp-fallback-test="false" title='"the" title'> <script src="~/blank.js" asp-fallback-src-include="**/site.js" asp-fallback-test="false" title='"the" title'>
// Fallback to globbed src // Fallback to globbed src
</script> </script>
<script src="~/styles/siteIntegrity.js?a=integrity"
asp-fallback-src="~/styles/sub/site2.js?a=integrity"
asp-fallback-test="true"
crossorigin="anonymous"
integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script loading primary source, applied integrity hash to primary source.
</script>
<script src="~/styles/siteIntegrity.js?a=integrity"
asp-fallback-src="~/styles/sub/siteIntegrity2.js?a=integrity"
asp-fallback-test="false"
asp-fallback-integrity-check="true"
crossorigin="anonymous"
integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, applies integrity hash to fallback.
</script>
<script src="~/styles/siteIntegrity.js?a=integrity"
asp-fallback-src="~/styles/sub/siteIntegrity3.js?a=integrity"
asp-fallback-test="false"
asp-fallback-integrity-check="false"
crossorigin="anonymous"
integrity="sha256-tMQLOHBNPE829MHQPO8metegsGobA/henDPOvtZOWhQ=">
// Script uses fallback source, ignores integrity hash on fallback.
</script>
<script src="~/blank.js" <script src="~/blank.js"
asp-fallback-src-include="**/*.js" asp-fallback-src-include="**/*.js"

View File

@ -0,0 +1,6 @@
body::after {
display: block;
color: #0fa912;
margin-top: 2.4em;
content: "Stylesheet 'siteIntegrity.css' loaded successfully!";
}

View File

@ -0,0 +1,6 @@
(function () {
var p = document.createElement("P");
p.appendChild(document.createTextNode("Integrity Script loaded successfully!"));
p.style.color = "#0fa912";
document.body.appendChild(p);
})();

View File

@ -0,0 +1,6 @@
(function () {
var p = document.createElement("P");
p.appendChild(document.createTextNode("Integrity Script loaded successfully!"));
p.style.color = "#0fa912";
document.body.appendChild(p);
})();

View File

@ -0,0 +1,6 @@
(function () {
var p = document.createElement("P");
p.appendChild(document.createTextNode("Integrity Script with different hash loaded successfully!"));
p.style.color = "#0fa912";
document.body.appendChild(p);
})();