Implemented U4-1455 SurfaceController additionalRouteVal parameters should be encrypted
Fixed U4-1454SurfaceController additionalRouteVal parameters do not handle equals sign correctly Fixed U4-1453SurfaceController additionalRouteVal parameters not passed to controller action
This commit is contained in:
@@ -11,6 +11,7 @@ using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Web.Mvc;
|
||||
using umbraco;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
@@ -112,18 +113,36 @@ namespace Umbraco.Web
|
||||
viewContext.HttpContext.Server.UrlEncode(surfaceAction),
|
||||
area);
|
||||
|
||||
var additionalRouteValsAsQuery = additionalRouteVals.ToDictionary<object>().ToQueryString();
|
||||
if (!additionalRouteValsAsQuery.IsNullOrWhiteSpace())
|
||||
surfaceRouteParams = "&" + additionalRouteValsAsQuery;
|
||||
//var additionalRouteValsAsQuery = additionalRouteVals.ToDictionary<object>().ToQueryString();
|
||||
|
||||
_base64String = Convert.ToBase64String(Encoding.UTF8.GetBytes(surfaceRouteParams));
|
||||
//U4-1454 SurfaceController additionalRouteVal parameters do not handle equals sign correctly
|
||||
string additionalRouteValsAsQuery = string.Empty;
|
||||
var additionalRouteValsDict = additionalRouteVals.ToDictionary<object>();
|
||||
|
||||
foreach (var item in additionalRouteValsDict)
|
||||
{
|
||||
additionalRouteValsAsQuery += viewContext.HttpContext.Server.UrlEncode(item.Key) + "=" + viewContext.HttpContext.Server.UrlEncode(item.Value.ToString()) + "&";
|
||||
}
|
||||
|
||||
if (additionalRouteValsAsQuery.Length > 0)
|
||||
additionalRouteValsAsQuery = additionalRouteValsAsQuery.Substring(0, additionalRouteValsAsQuery.Length - 1);
|
||||
|
||||
if (!additionalRouteValsAsQuery.IsNullOrWhiteSpace())
|
||||
surfaceRouteParams += "&" + additionalRouteValsAsQuery;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(surfaceRouteParams))
|
||||
{
|
||||
//U4-1455 SurfaceController additionalRouteVal parameters should be encrypted
|
||||
var bytesToEncrypt = Encoding.UTF8.GetBytes(surfaceRouteParams);
|
||||
_encryptedString = MachineKey.Encode(bytesToEncrypt, MachineKeyProtection.All);
|
||||
}
|
||||
|
||||
_textWriter = viewContext.Writer;
|
||||
}
|
||||
|
||||
|
||||
private bool _disposed;
|
||||
private readonly string _base64String;
|
||||
private readonly string _encryptedString;
|
||||
private readonly TextWriter _textWriter;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
@@ -133,7 +152,7 @@ namespace Umbraco.Web
|
||||
this._disposed = true;
|
||||
|
||||
//write out the hidden surface form routes
|
||||
_textWriter.Write("<input name='uformpostroutevals' type='hidden' value='" + _base64String + "' />");
|
||||
_textWriter.Write("<input name='uformpostroutevals' type='hidden' value='" + _encryptedString + "' />");
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,22 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
public class RenderRouteHandler : IRouteHandler
|
||||
{
|
||||
|
||||
// Define reserved dictionary keys for controller, action and area specified in route additional values data
|
||||
private static string RESERVED_ADDITIONAL_KEY_CONTROLLER = "c";
|
||||
private static string RESERVED_ADDITIONAL_KEY_ACTION = "a";
|
||||
private static string RESERVED_ADDITIONAL_KEY_AREA = "ar";
|
||||
private static string[] RESERVED_ADDITIONAL_KEYS = new string[] {
|
||||
RESERVED_ADDITIONAL_KEY_CONTROLLER,
|
||||
RESERVED_ADDITIONAL_KEY_ACTION,
|
||||
RESERVED_ADDITIONAL_KEY_AREA };
|
||||
|
||||
public RenderRouteHandler(IControllerFactory controllerFactory)
|
||||
{
|
||||
if (controllerFactory == null) throw new ArgumentNullException("controllerFactory");
|
||||
@@ -91,6 +101,45 @@ namespace Umbraco.Web.Mvc
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-context", UmbracoContext); //required for UmbracoTemplatePage
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt additional route values
|
||||
/// </summary>
|
||||
/// <param name="requestContext"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<string, string> AdditionalRouteValues(RequestContext requestContext)
|
||||
{
|
||||
Dictionary<string, string> values = new Dictionary<string, string>();
|
||||
|
||||
if (requestContext.HttpContext.Request.RequestType != "POST")
|
||||
return values;
|
||||
|
||||
//this field will contain a base64 encoded version of the surface route vals
|
||||
if (requestContext.HttpContext.Request["uformpostroutevals"].IsNullOrWhiteSpace())
|
||||
return values;
|
||||
|
||||
var encodedVal = requestContext.HttpContext.Request["uformpostroutevals"];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(encodedVal))
|
||||
{
|
||||
// Decrypt additional values
|
||||
var decodedBytes = MachineKey.Decode(encodedVal, MachineKeyProtection.All);
|
||||
var decodedString = Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
// Parse as query string
|
||||
var decodedParts = decodedString.Split('&').Select(x => new { Key = x.Split('=')[0], Value = x.Split('=')[1] }).ToArray();
|
||||
|
||||
if (decodedParts != null)
|
||||
{
|
||||
foreach (var part in decodedParts)
|
||||
{
|
||||
values[part.Key] = HttpUtility.UrlDecode(part.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the request and query strings to see if it matches the definition of having a Surface controller
|
||||
/// posted value, if so, then we return a PostedDataProxyInfo object with the correct information.
|
||||
@@ -106,22 +155,20 @@ namespace Umbraco.Web.Mvc
|
||||
if (requestContext.HttpContext.Request["uformpostroutevals"].IsNullOrWhiteSpace())
|
||||
return null;
|
||||
|
||||
var encodedVal = requestContext.HttpContext.Request["uformpostroutevals"];
|
||||
var decodedString = Encoding.UTF8.GetString(Convert.FromBase64String(encodedVal));
|
||||
//the value is formatted as query strings
|
||||
var decodedParts = decodedString.Split('&').Select(x => new { Key = x.Split('=')[0], Value = x.Split('=')[1] }).ToArray();
|
||||
// U4-1455 SurfaceController additionalRouteVal parameters should be encrypted
|
||||
var decodedParts = AdditionalRouteValues(requestContext);
|
||||
|
||||
//validate all required keys exist
|
||||
|
||||
//the controller
|
||||
if (!decodedParts.Any(x => x.Key == "c"))
|
||||
return null;
|
||||
//the action
|
||||
if (!decodedParts.Any(x => x.Key == "a"))
|
||||
return null;
|
||||
//the area
|
||||
if (!decodedParts.Any(x => x.Key == "ar"))
|
||||
return null;
|
||||
if (!decodedParts.Any(x => x.Key == RESERVED_ADDITIONAL_KEY_CONTROLLER))
|
||||
return null;
|
||||
//the action
|
||||
if (!decodedParts.Any(x => x.Key == RESERVED_ADDITIONAL_KEY_ACTION))
|
||||
return null;
|
||||
//the area
|
||||
if (!decodedParts.Any(x => x.Key == RESERVED_ADDITIONAL_KEY_AREA))
|
||||
return null;
|
||||
|
||||
////the controller type, if it contains this then it is a plugin controller, not locally declared.
|
||||
//if (decodedParts.Any(x => x.Key == "t"))
|
||||
@@ -135,12 +182,19 @@ namespace Umbraco.Web.Mvc
|
||||
// };
|
||||
//}
|
||||
|
||||
//U4-1453 SurfaceController additionalRouteVal parameters not passed to controller action
|
||||
foreach (var item in decodedParts.Where(x => !RESERVED_ADDITIONAL_KEYS.Contains(x.Key)))
|
||||
{
|
||||
// Populate route with additional values which aren't reserved values
|
||||
requestContext.RouteData.Values.Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
//return the proxy info without the surface id... could be a local controller.
|
||||
return new PostedDataProxyInfo
|
||||
{
|
||||
ControllerName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "c").Value),
|
||||
ActionName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "a").Value),
|
||||
Area = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == "ar").Value),
|
||||
ControllerName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == RESERVED_ADDITIONAL_KEY_CONTROLLER).Value),
|
||||
ActionName = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == RESERVED_ADDITIONAL_KEY_ACTION).Value),
|
||||
Area = requestContext.HttpContext.Server.UrlDecode(decodedParts.Single(x => x.Key == RESERVED_ADDITIONAL_KEY_AREA).Value),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user