Change priority for request token source lookup. Header token now takes priority over form field token.
This commit is contained in:
parent
f65c3db6ef
commit
3595452af7
|
|
@ -44,8 +44,16 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
|
|
||||||
var cookieToken = httpContext.Request.Cookies[_options.CookieName];
|
var cookieToken = httpContext.Request.Cookies[_options.CookieName];
|
||||||
|
|
||||||
|
// We want to delay reading the form as much as possible, for example in case of large file uploads,
|
||||||
|
// request token could be part of the header.
|
||||||
StringValues requestToken;
|
StringValues requestToken;
|
||||||
if (httpContext.Request.HasFormContentType)
|
if (_options.HeaderName != null)
|
||||||
|
{
|
||||||
|
requestToken = httpContext.Request.Headers[_options.HeaderName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to reading form instead
|
||||||
|
if (requestToken.Count == 0 && httpContext.Request.HasFormContentType)
|
||||||
{
|
{
|
||||||
// Check the content-type before accessing the form collection to make sure
|
// Check the content-type before accessing the form collection to make sure
|
||||||
// we report errors gracefully.
|
// we report errors gracefully.
|
||||||
|
|
@ -53,12 +61,6 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
requestToken = form[_options.FormFieldName];
|
requestToken = form[_options.FormFieldName];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to header if the form value was not provided.
|
|
||||||
if (requestToken.Count == 0 && _options.HeaderName != null)
|
|
||||||
{
|
|
||||||
requestToken = httpContext.Request.Headers[_options.HeaderName];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AntiforgeryTokenSet(requestToken, cookieToken, _options.FormFieldName, _options.HeaderName);
|
return new AntiforgeryTokenSet(requestToken, cookieToken, _options.FormFieldName, _options.HeaderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Internal;
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
|
|
@ -99,39 +100,15 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetRequestTokens_NonFormContentType_HeaderDisabled_ReturnsNullToken()
|
public async Task GetRequestTokens_HeaderTokenTakensPriority_OverFormToken()
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
|
||||||
httpContext.Request.ContentType = "application/json";
|
|
||||||
|
|
||||||
// Will not be accessed
|
|
||||||
httpContext.Request.Form = null;
|
|
||||||
|
|
||||||
var options = new AntiforgeryOptions()
|
|
||||||
{
|
|
||||||
CookieName = "cookie-name",
|
|
||||||
FormFieldName = "form-field-name",
|
|
||||||
HeaderName = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var tokenSet = await tokenStore.GetRequestTokensAsync(httpContext);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("cookie-value", tokenSet.CookieToken);
|
|
||||||
Assert.Null(tokenSet.RequestToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetRequestTokens_FormContentType_FallbackHeaderToken()
|
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
||||||
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
|
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
|
||||||
httpContext.Request.Form = FormCollection.Empty;
|
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
|
||||||
|
{
|
||||||
|
{ "form-field-name", "form-value" },
|
||||||
|
}); // header value has priority.
|
||||||
httpContext.Request.Headers.Add("header-name", "header-value");
|
httpContext.Request.Headers.Add("header-name", "header-value");
|
||||||
|
|
||||||
var options = new AntiforgeryOptions()
|
var options = new AntiforgeryOptions()
|
||||||
|
|
@ -151,6 +128,34 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
Assert.Equal("header-value", tokens.RequestToken);
|
Assert.Equal("header-value", tokens.RequestToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetRequestTokens_NoHeaderToken_FallsBackToFormToken()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
||||||
|
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
|
||||||
|
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
|
||||||
|
{
|
||||||
|
{ "form-field-name", "form-value" },
|
||||||
|
});
|
||||||
|
|
||||||
|
var options = new AntiforgeryOptions()
|
||||||
|
{
|
||||||
|
CookieName = "cookie-name",
|
||||||
|
FormFieldName = "form-field-name",
|
||||||
|
HeaderName = "header-name",
|
||||||
|
};
|
||||||
|
|
||||||
|
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("cookie-value", tokens.CookieToken);
|
||||||
|
Assert.Equal("form-value", tokens.RequestToken);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetRequestTokens_NonFormContentType_UsesHeaderToken()
|
public async Task GetRequestTokens_NonFormContentType_UsesHeaderToken()
|
||||||
{
|
{
|
||||||
|
|
@ -180,7 +185,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetRequestTokens_NonFormContentType_NoHeaderToken_ReturnsNullToken()
|
public async Task GetRequestTokens_NoHeaderToken_NonFormContentType_ReturnsNullToken()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
||||||
|
|
@ -207,7 +212,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GetRequestTokens_BothFieldsEmpty_ReturnsNullTokens()
|
public async Task GetRequestTokens_BothHeaderValueAndFormFieldsEmpty_ReturnsNullTokens()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
||||||
|
|
@ -231,35 +236,6 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||||
Assert.Null(tokenSet.RequestToken);
|
Assert.Null(tokenSet.RequestToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetFormToken_FormFieldIsValid_ReturnsToken()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var httpContext = GetHttpContext("cookie-name", "cookie-value");
|
|
||||||
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
|
|
||||||
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
|
|
||||||
{
|
|
||||||
{ "form-field-name", "form-value" },
|
|
||||||
});
|
|
||||||
httpContext.Request.Headers.Add("header-name", "header-value"); // form value has priority.
|
|
||||||
|
|
||||||
var options = new AntiforgeryOptions()
|
|
||||||
{
|
|
||||||
CookieName = "cookie-name",
|
|
||||||
FormFieldName = "form-field-name",
|
|
||||||
HeaderName = "header-name",
|
|
||||||
};
|
|
||||||
|
|
||||||
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.Equal("cookie-value", tokens.CookieToken);
|
|
||||||
Assert.Equal("form-value", tokens.RequestToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true, true)]
|
[InlineData(true, true)]
|
||||||
[InlineData(false, null)]
|
[InlineData(false, null)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue