Revert "Added SetAntiForgeryCookieAndHeader method that sets cookie token and header"

This reverts commit 951ed05893.
This commit is contained in:
Pranav K 2015-01-20 00:49:15 -08:00
parent 951ed05893
commit c8a13087a6
9 changed files with 20 additions and 345 deletions

View File

@ -97,14 +97,5 @@ namespace Microsoft.AspNet.Mvc
{
Validate(context, antiForgeryTokenSet.CookieToken, antiForgeryTokenSet.FormToken);
}
/// <summary>
/// Generates and sets an anti-forgery cookie if one is not available or not valid. Also sets response headers.
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
public void SetCookieTokenAndHeader([NotNull] HttpContext context)
{
_worker.SetCookieTokenAndHeader(context);
}
}
}

View File

@ -102,8 +102,19 @@ namespace Microsoft.AspNet.Mvc
var tokenSet = GetTokens(httpContext, oldCookieToken);
var newCookieToken = tokenSet.CookieToken;
var formToken = tokenSet.FormToken;
if (newCookieToken != null)
{
// If a new cookie was generated, persist it.
_tokenStore.SaveCookieToken(httpContext, newCookieToken);
}
SaveCookieTokenAndHeader(httpContext, newCookieToken);
if (!_config.SuppressXFrameOptionsHeader)
{
// Adding X-Frame-Options header to prevent ClickJacking. See
// http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-10
// for more information.
httpContext.Response.Headers.Set("X-Frame-Options", "SAMEORIGIN");
}
// <input type="hidden" name="__AntiForgeryToken" value="..." />
var retVal = new TagBuilder("input");
@ -132,11 +143,15 @@ namespace Microsoft.AspNet.Mvc
private AntiForgeryTokenSetInternal GetTokens(HttpContext httpContext, AntiForgeryToken oldCookieToken)
{
var newCookieToken = ValidateAndGenerateNewToken(oldCookieToken);
if (newCookieToken != null)
AntiForgeryToken newCookieToken = null;
if (!_validator.IsCookieTokenValid(oldCookieToken))
{
oldCookieToken = newCookieToken;
// Need to make sure we're always operating with a good cookie token.
oldCookieToken = newCookieToken = _generator.GenerateCookieToken();
}
Debug.Assert(_validator.IsCookieTokenValid(oldCookieToken));
var formToken = _generator.GenerateFormToken(
httpContext,
ExtractIdentity(httpContext),
@ -189,54 +204,6 @@ namespace Microsoft.AspNet.Mvc
deserializedFormToken);
}
/// <summary>
/// Generates and sets an anti-forgery cookie if one is not available or not valid. Also sets response headers.
/// </summary>
/// <param name="context">The HTTP context associated with the current call.</param>
public void SetCookieTokenAndHeader([NotNull] HttpContext httpContext)
{
CheckSSLConfig(httpContext);
var oldCookieToken = GetCookieTokenNoThrow(httpContext);
var newCookieToken = ValidateAndGenerateNewToken(oldCookieToken);
SaveCookieTokenAndHeader(httpContext, newCookieToken);
}
// This method returns null if oldCookieToken is valid.
private AntiForgeryToken ValidateAndGenerateNewToken(AntiForgeryToken oldCookieToken)
{
if (!_validator.IsCookieTokenValid(oldCookieToken))
{
// Need to make sure we're always operating with a good cookie token.
var newCookieToken = _generator.GenerateCookieToken();
Debug.Assert(_validator.IsCookieTokenValid(newCookieToken));
return newCookieToken;
}
return null;
}
private void SaveCookieTokenAndHeader(
[NotNull] HttpContext httpContext,
AntiForgeryToken newCookieToken)
{
if (newCookieToken != null)
{
// Persist the new cookie if it is not null.
_tokenStore.SaveCookieToken(httpContext, newCookieToken);
}
if (!_config.SuppressXFrameOptionsHeader)
{
// Adding X-Frame-Options header to prevent ClickJacking. See
// http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-10
// for more information.
httpContext.Response.Headers.Set("X-Frame-Options", "SAMEORIGIN");
}
}
private class AntiForgeryTokenSetInternal
{
public AntiForgeryToken FormToken { get; set; }

View File

@ -561,10 +561,7 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <returns>A<see cref="Task{HtmlString}"/> that represents the asynchronous flush operation and on
/// completion returns a <see cref="HtmlString.Empty"/>.</returns>
/// <remarks>The value returned is a token value that allows FlushAsync to work directly in an HTML
/// section. However the value does not represent the rendered content.
/// This method also writes out headers, so any modifications to headers must be done before FulshAsync is
/// called. For example, call <see cref="SetAntiForgeryCookieAndHeader"/> to send anti-forgery cookie token
/// and X-Frame-Options header to client before this method flushes headers out. </remarks>
/// section. However the value does not represent the rendered content.</remarks>
public async Task<HtmlString> FlushAsync()
{
// If there are active writing scopes then we should throw. Cannot flush content that has the potential to
@ -620,20 +617,6 @@ namespace Microsoft.AspNet.Mvc.Razor
PageExecutionContext?.EndContext();
}
/// <summary>
/// Sets anti-forgery cookie and X-Frame-Options header on the response.
/// </summary>
/// <returns>A <see cref="HtmlString"/> that returns a <see cref="HtmlString.Empty"/>.</returns>
/// <remarks> Call this method to send anti-forgery cookie token and X-Frame-Options header to client
/// before <see cref="FlushAsync"/> flushes the headers. </remarks>
public virtual HtmlString SetAntiForgeryCookieAndHeader()
{
var antiForgery = Context.RequestServices.GetRequiredService<AntiForgery>();
antiForgery.SetCookieTokenAndHeader(Context);
return HtmlString.Empty;
}
private void EnsureMethodCanBeInvoked(string methodName)
{
if (PreviousSectionWriters == null)

View File

@ -379,29 +379,6 @@ namespace Microsoft.AspNet.Mvc.Core.Test
context.TokenProvider.Verify();
}
[Theory]
[InlineData(false, "SAMEORIGIN")]
[InlineData(true, null)]
public void SetCookieTokenAndHeader_AddsXFrameOptionsHeader(bool suppressXFrameOptions, string expectedHeaderValue)
{
// Arrange
var options = new AntiForgeryOptions()
{
SuppressXFrameOptionsHeader = suppressXFrameOptions
};
// Genreate a new cookie.
var context = GetAntiForgeryWorkerContext(options, useOldCookie: false, isOldCookieValid: false);
var worker = GetAntiForgeryWorker(context);
// Act
worker.SetCookieTokenAndHeader(context.HttpContext.Object);
// Assert
var xFrameOptions = context.HttpContext.Object.Response.Headers["X-Frame-Options"];
Assert.Equal(expectedHeaderValue, xFrameOptions);
}
private AntiForgeryWorker GetAntiForgeryWorker(AntiForgeryWorkerContext context)
{
return new AntiForgeryWorker(

View File

@ -234,117 +234,5 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal("The required anti-forgery form field \"__RequestVerificationToken\" is not present.",
exception.ExceptionMessage);
}
[Fact]
public async Task SetCookieAndHeaderBeforeFlushAsync_GeneratesCookieTokenAndHeader()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Account/FlushAsyncLogin");
// Assert
var header = Assert.Single(response.Headers.GetValues("X-Frame-Options"));
Assert.Equal("SAMEORIGIN", header);
var setCookieHeader = response.Headers.GetValues("Set-Cookie").ToArray();
var cookie = Assert.Single(setCookieHeader);
Assert.True(cookie.StartsWith("__RequestVerificationToken"));
}
[Fact]
public async Task SetCookieAndHeaderBeforeFlushAsync_PostToForm()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// do a get response.
var getResponse = await client.GetAsync("http://localhost/Account/FlushAsyncLogin");
var resposneBody = await getResponse.Content.ReadAsStringAsync();
var formToken = AntiForgeryTestHelper.RetrieveAntiForgeryToken(resposneBody, "Account/FlushAsyncLogin");
var cookieToken = AntiForgeryTestHelper.RetrieveAntiForgeryCookie(getResponse);
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Account/FlushAsyncLogin");
request.Headers.Add("Cookie", "__RequestVerificationToken=" + cookieToken);
var nameValueCollection = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string,string>("__RequestVerificationToken", formToken),
new KeyValuePair<string,string>("UserName", "test"),
new KeyValuePair<string,string>("Password", "password"),
};
request.Content = new FormUrlEncodedContent(nameValueCollection);
// Act
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("OK", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task FlushAsyncBeforeAntiForgery_CookieAndHeaderNotInResponse()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Account/FlushWithoutUpdatingHeader");
// Assert
IEnumerable<string> returnList;
Assert.False(response.Headers.TryGetValues("Set-Cookie", out returnList));
Assert.False(response.Headers.TryGetValues("X-Frame-Options", out returnList));
}
[Fact]
public async Task FlushAsyncBeforeAntiForgery_PostToForm()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.CreateClient();
// do a get response.
var getResponse = await client.GetAsync("http://localhost/Account/FlushWithoutUpdatingHeader");
var resposneBody = await getResponse.Content.ReadAsStringAsync();
// Assert - 1
IEnumerable<string> returnList;
Assert.False(getResponse.Headers.TryGetValues("Set-Cookie", out returnList));
Assert.False(getResponse.Headers.TryGetValues("X-Frame-Options", out returnList));
var formToken = AntiForgeryTestHelper.RetrieveAntiForgeryToken(
resposneBody,
"Account/FlushWithoutUpdatingHeader");
var request = new HttpRequestMessage(
HttpMethod.Post,
"http://localhost/Account/FlushWithoutUpdatingHeader");
var nameValueCollection = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string,string>("__RequestVerificationToken", formToken),
new KeyValuePair<string,string>("UserName", "test"),
new KeyValuePair<string,string>("Password", "password"),
};
request.Content = new FormUrlEncodedContent(nameValueCollection);
// Act
var response = await client.SendAsync(request);
// Assert - 2
var exception = response.GetServerException();
Assert.Equal("The required anti-forgery cookie \"__RequestVerificationToken\" is not present.",
exception.ExceptionMessage);
}
}
}

View File

@ -31,41 +31,5 @@ namespace AntiForgeryWebSite
{
return "OK";
}
// GET: /Account/FlushAsyncLogin
[AllowAnonymous]
public ActionResult FlushAsyncLogin(string returnUrl = null)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
// POST: /Account/FlushAsyncLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public string FlushAsyncLogin(LoginViewModel model)
{
return "OK";
}
// GET: /Account/FlushWithoutUpdatingHeader
[AllowAnonymous]
public ActionResult FlushWithoutUpdatingHeader(string returnUrl = null)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
// POST: /Account/FlushWithoutUpdatingHeader
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public string FlushWithoutUpdatingHeader(LoginViewModel model)
{
return "OK";
}
}
}

View File

@ -1,43 +0,0 @@
@model AntiForgeryWebSite.LoginViewModel
@{
ViewBag.Title = "Log in";
Layout = "/Views/Shared/_FlushAsyncLayout.cshtml";
}
@section Login
{
<h2>@ViewBag.Title.</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("FlushAsyncLogin", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2", ClAsS = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "...", cLass = "form-control" })
@Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
}
</section>
</div>
</div>
}

View File

@ -1,37 +0,0 @@
@model AntiForgeryWebSite.LoginViewModel
@await FlushAsync()
<h2>@ViewBag.Title.</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
@using (Html.BeginForm("FlushWithoutUpdatingHeader", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2", ClAsS = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "...", cLass = "form-control" })
@Html.ValidationMessageFor(m => m.UserName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
}
</section>
</div>
</div>

View File

@ -1,15 +0,0 @@
<html>
<head>
<title>@ViewBag.Title AntiForgery Functional Tests</title>
</head>
@SetAntiForgeryCookieAndHeader()
@await FlushAsync()
<body>
@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })
<div class="container body-content">
@RenderBody()
@await RenderSectionAsync("Login", required: false)
</div>
</body>
</html>