Added some hacks to get http get calls to be validated when an attribute exists on a controller action

--HG--
branch : dev
This commit is contained in:
Erik Porter
2010-02-16 15:27:30 -08:00
parent 06e36a9a37
commit 7d543e14d3
5 changed files with 106 additions and 9 deletions

View File

@@ -8,6 +8,7 @@ using Orchard.Core.Navigation.Models;
using Orchard.Core.Navigation.Services;
using Orchard.Core.Navigation.ViewModels;
using Orchard.Localization;
using Orchard.Mvc.Attributes;
using Orchard.UI.Navigation;
using Orchard.Utility;
using MenuItem=Orchard.Core.Navigation.Models.MenuItem;
@@ -100,7 +101,7 @@ namespace Orchard.Core.Navigation.Controllers {
return RedirectToAction("Index");
}
//[ValidateAntiForgeryTokenOrchard]
[ValidateAntiForgeryTokenOrchard]
public ActionResult Delete(int id) {
if (!_services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu")))
return new HttpUnauthorizedResult();

View File

@@ -37,6 +37,8 @@ namespace Orchard.Web {
}
protected void Application_BeginRequest() {
Context.Items["originalHttpContext"] = Context;
_host.BeginRequest();
}

View File

@@ -0,0 +1,8 @@
using System;
using System.Web.Mvc;
namespace Orchard.Mvc.Attributes {
[AttributeUsage(AttributeTargets.Method)]
public class ValidateAntiForgeryTokenOrchardAttribute : FilterAttribute {
}
}

View File

@@ -1,5 +1,8 @@
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.Mvc.Attributes;
using Orchard.Security;
using Orchard.Settings;
@@ -15,17 +18,99 @@ namespace Orchard.Mvc.Filters {
}
public void OnAuthorization(AuthorizationContext filterContext) {
// not a post: no work to do
if (filterContext.HttpContext.Request.HttpMethod != "POST")
if ((filterContext.HttpContext.Request.HttpMethod != "POST" ||
_authenticationService.GetAuthenticatedUser() == null) && !ShouldValidateGet(filterContext)) {
return;
// not logged in: no attack vector
if (_authenticationService.GetAuthenticatedUser() == null)
return;
}
var siteSalt = _siteService.GetSiteSettings().SiteSalt;
var validator = new ValidateAntiForgeryTokenAttribute { Salt = siteSalt };
var validator = new ValidateAntiForgeryTokenAttribute {Salt = siteSalt};
validator.OnAuthorization(filterContext);
if (filterContext.HttpContext is HackHttpContext)
filterContext.HttpContext = ((HackHttpContext)filterContext.HttpContext).OriginalHttpContextBase;
}
private static bool ShouldValidateGet(AuthorizationContext context) {
const string tokenFieldName = "__RequestVerificationToken";
var attributes =
(ValidateAntiForgeryTokenOrchardAttribute[])
context.ActionDescriptor.GetCustomAttributes(typeof (ValidateAntiForgeryTokenOrchardAttribute), false);
if (attributes.Length > 0) {
var request = context.HttpContext.Request;
//HAACK: (erikpo) If the token is in the querystring, put it in the form so MVC can validate it
if (!string.IsNullOrEmpty(request.QueryString[tokenFieldName])) {
context.HttpContext = new HackHttpContext(context.HttpContext, (HttpContext)context.HttpContext.Items["originalHttpContext"]);
((HackHttpRequest)context.HttpContext.Request).AddFormValue(tokenFieldName, context.HttpContext.Request.QueryString[tokenFieldName]);
return true;
}
}
return false;
}
#region HackHttpContext
private class HackHttpContext : HttpContextWrapper {
private readonly HttpContextBase _originalHttpContextBase;
private readonly HttpContext _originalHttpContext;
private HttpRequestWrapper _request;
public HackHttpContext(HttpContextBase httpContextBase, HttpContext httpContext)
: base(httpContext) {
_originalHttpContextBase = httpContextBase;
_originalHttpContext = httpContext;
}
public HttpContextBase OriginalHttpContextBase {
get { return _originalHttpContextBase; }
}
public override HttpRequestBase Request
{
get
{
if (_request == null)
_request = new HackHttpRequest(_originalHttpContext.Request);
return _request;
}
}
}
#endregion
#region HackHttpRequest
private class HackHttpRequest : HttpRequestWrapper {
private readonly HttpRequest _originalHttpRequest;
private NameValueCollection _form;
public HackHttpRequest(HttpRequest httpRequest)
: base(httpRequest) {
_originalHttpRequest = httpRequest;
}
public override NameValueCollection Form
{
get
{
if (_form == null)
_form = new NameValueCollection(_originalHttpRequest.Form);
return _form;
}
}
public void AddFormValue(string key, string value) {
Form.Add(key, value);
}
}
#endregion
}
}

View File

@@ -151,6 +151,7 @@
<Compile Include="Extensions\ExtensionFolders.cs" />
<Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="Mvc\Attributes\ValidateAntiForgeryTokenOrchardAttribute.cs" />
<Compile Include="OrchardException.cs" />
<Compile Include="Security\IAuthorizationServiceEvents.cs" />
<Compile Include="Security\StandardPermissions.cs" />