Add configure delegate for CookieOptions

- allows configuration of CookieOptions such as SameSite without explicit duplication of the option on AntiforgeryOptions
This commit is contained in:
John Luo 2017-05-22 01:19:34 -07:00
parent 8f8f3bce63
commit 5870fce035
3 changed files with 34 additions and 22 deletions

View File

@ -47,18 +47,30 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
/// <summary> /// <summary>
/// This is obsolete and will be removed in a future version.
/// The recommended alternative is to use ConfigureCookieOptions.
/// The path set on the cookie. If set to <c>null</c>, the "path" attribute on the cookie is set to the current /// The path set on the cookie. If set to <c>null</c>, the "path" attribute on the cookie is set to the current
/// request's <see cref="HttpRequest.PathBase"/> value. If the value of <see cref="HttpRequest.PathBase"/> is /// request's <see cref="HttpRequest.PathBase"/> value. If the value of <see cref="HttpRequest.PathBase"/> is
/// <c>null</c> or empty, then the "path" attribute is set to the value of <see cref="CookieOptions.Path"/>. /// <c>null</c> or empty, then the "path" attribute is set to the value of <see cref="CookieOptions.Path"/>.
/// </summary> /// </summary>
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use ConfigureCookieOptions.")]
public PathString? CookiePath { get; set; } public PathString? CookiePath { get; set; }
/// <summary> /// <summary>
/// The domain set on the cookie. By default its <c>null</c> which results in the "domain" attribute not being /// This is obsolete and will be removed in a future version.
/// set. /// The recommended alternative is to use ConfigureCookieOptions.
/// The domain set on the cookie. By default its <c>null</c> which results in the "domain" attribute not being set.
/// </summary> /// </summary>
[Obsolete("This is obsolete and will be removed in a future version. The recommended alternative is to use ConfigureCookieOptions.")]
public string CookieDomain { get; set; } public string CookieDomain { get; set; }
/// <summary>
/// Configures the <see cref="CookieOptions"/> of the antiforgery cookies. Without additional configuration, the
/// default values antiforgery cookie options are true for <see cref="CookieOptions.HttpOnly"/>, null for
/// <see cref="CookieOptions.Domain"/> and <see cref="SameSiteMode.Strict"/> for <see cref="CookieOptions.SameSite"/>.
/// </summary>
public Action<HttpContext, CookieOptions> ConfigureCookieOptions { get; set; }
/// <summary> /// <summary>
/// Specifies the name of the antiforgery token field that is used by the antiforgery system. /// Specifies the name of the antiforgery token field that is used by the antiforgery system.
/// </summary> /// </summary>

View File

@ -69,34 +69,34 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Debug.Assert(httpContext != null); Debug.Assert(httpContext != null);
Debug.Assert(token != null); Debug.Assert(token != null);
var options = new CookieOptions(); var options = new CookieOptions
options.HttpOnly = true;
options.Domain = _options.CookieDomain;
// Note: don't use "newCookie.Secure = _options.RequireSSL;" since the default
// value of newCookie.Secure is populated out of band.
if (_options.RequireSsl)
{ {
options.Secure = true; HttpOnly = true,
} #pragma warning disable 618
SetCookiePath(httpContext, options); Domain = _options.CookieDomain,
#pragma warning restore 618
SameSite = SameSiteMode.Strict,
Secure = _options.RequireSsl
};
httpContext.Response.Cookies.Append(_options.CookieName, token, options); #pragma warning disable 618
}
private void SetCookiePath(HttpContext httpContext, CookieOptions cookieOptions)
{
if (_options.CookiePath != null) if (_options.CookiePath != null)
{ {
cookieOptions.Path = _options.CookiePath.ToString(); options.Path = _options.CookiePath.ToString();
} }
#pragma warning restore 618
else else
{ {
var pathBase = httpContext.Request.PathBase.ToString(); var pathBase = httpContext.Request.PathBase.ToString();
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
cookieOptions.Path = pathBase; options.Path = pathBase;
} }
} }
_options.ConfigureCookieOptions?.Invoke(httpContext, options);
httpContext.Response.Cookies.Append(_options.CookieName, token, options);
} }
} }
} }

View File

@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
} }
[Fact] [Fact]
public void SaveCookieToken_NonNullAntiforgeryOptionsCookiePath_UsesOptionsCookiePath() public void SaveCookieToken_NonNullAntiforgeryOptionsConfigureCookieOptionsPath_UsesCookieOptionsPath()
{ {
// Arrange // Arrange
var expectedCookiePath = "/"; var expectedCookiePath = "/";
@ -330,7 +330,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
.Returns("/index.html"); .Returns("/index.html");
var options = new AntiforgeryOptions(); var options = new AntiforgeryOptions();
options.CookieName = _cookieName; options.CookieName = _cookieName;
options.CookiePath = expectedCookiePath; options.ConfigureCookieOptions = (context, cookieOptions) => cookieOptions.Path = expectedCookiePath;
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options)); var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
// Act // Act
@ -346,7 +346,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
} }
[Fact] [Fact]
public void SaveCookieToken_NonNullAntiforgeryOptionsCookieDomain_UsesOptionsCookieDomain() public void SaveCookieToken_NonNullAntiforgeryOptionsConfigureCookieOptionsDomain_UsesCookieOptionsDomain()
{ {
// Arrange // Arrange
var expectedCookieDomain = "microsoft.com"; var expectedCookieDomain = "microsoft.com";
@ -364,7 +364,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
.Returns("/index.html"); .Returns("/index.html");
var options = new AntiforgeryOptions(); var options = new AntiforgeryOptions();
options.CookieName = _cookieName; options.CookieName = _cookieName;
options.CookieDomain = expectedCookieDomain; options.ConfigureCookieOptions = (context, cookieOptions) => cookieOptions.Domain = expectedCookieDomain;
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options)); var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
// Act // Act