-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Security trimming does not pass querystring parameters to custom authorizeattributes #412
Comments
First of all, query string parameters are not part of routing - MVC does not add them into the RouteValueCollection. But that is not the only issue with this expectation. Perhaps there is a solution for what you are trying to achieve, but it would be helpful to know what that goal is. |
You create HttpContext by route data (RouteValueDictionary) and it contains querystring. With default routing all action parameters exept ids become querystring parameters. Then you through away it. And you call custom authorize attribute without this part of the path. Many my methods contain Method parameter and user have roles for this methods. I wrote custom authorize attribure for this check. To be precisely I check Request.Unvalidated(). It worked correctly with security check but was unexpectedly broken with security trimming. (I have feeling that it worked for sometime.) You correctly check all authorize attributes that the node has. And it means that somebody thought which attibutes have sense for current node. So there is no much problem with every node and so on. |
It is unclear what you mean by "throwing it away" at this point. If you could provide a code sample of what you did as a workaround it would help with my understanding of the issue. You could also try this alternative AuthorizeAttributeAclModule to see if that works for you. I would appreciate if you could make this clear - I am working on a patch release right now and it would be nice to include a fix for this, if possible. |
The original mvc routedata consept was as in http://www.tutorialsteacher.com/articles/what_is_routedata that routedata includes action parameters. But as understand it was removed (or processed after authorizeattribute). And there are suggestions to use filterContext.Controller.ValueProvider instead (http://stackoverflow.com/questions/5549371/using-action-parameters-in-custom-authorization-attribute-in-asp-net-mvc3). I use MVC 4 and nugets 4.6.18 and I transfer routedata from node to authorization attribute explicitly because I don't get action parameters. They go to querystring and should be accessed through value provider or request.querystring. FindRoutesForNode - create httpcontext by node routedata. And it contains routevalues and querystring. But querystring part is thrown away. MVC pass all the data to custom authorize attribute and attribute works. |
Alternative gaves empty result on FindSiteMapNode and menu is empty with it. |
MVC always runs
Correct Aside from this chicken-and-egg problem with checking security for other pages than the current one which MVC doesn't do at all and we do, Microsoft has made it pretty clear that you are not supposed to make a security scheme based on the URL. The purpose of If I misunderstand and you are not using those values for security but for redirecting your request as in the example you linked to, do note that there is a protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string)
?? (httpContext.Request["id"] as string);
if (string.IsNullOrEmpty(id))
{
// Query string doesn't exist, so just use the default logic
base.HandleUnauthorizedRequest(filterContext);
}
else
{
// Set your custom result handler here
filterContext.Result =
}
} |
Node has many additional attributes. Most used to create url as routevalues. Only Id and parameters with route configuration can be used in authorization attribute. Why? Why behavior depends on route definition? MyAuthorizeAttribute in the sample checks that you are authorized this attribute value (id =8). It goes to routedata by default. And it works with SiteMap the same as with MVC. If you rename it to something like "objectId" it would work only with MVC, not SiteMap. This security check works on access to the page, not on creating of querystring. So it is impossible use unautorized querystring value. |
Because MVC depends on routing to work. However, there is another option - set the URL property of the node and then you will have a URL-based node. You could potentially put a query string in there if you really need one.
Not true. You need to account for every route value in the node. The value "objectId" would need to be added either to
I don't understand what you mean by this. Again, unless you provide some code to make this discussion clear, I probably won't be able to help you. |
I thought that preservedRouteParamters means use value from current path. You removed attributesToIgnore? |
I was able to track down one of the issues with this, but I am unable to work out how to make the ValueProvider function. I went through the source code of MVC, but it didn't seem to be much help. If you grab the 2 files from this gist, and update your DI configuration as follows, you will be able to use the var excludeTypes = new Type[] {
// Use this array to add types you wish to explicitly exclude from convention-based
// auto-registration. By default all types that either match I[TypeName] = [TypeName] or
// I[TypeName] = [TypeName]Adapter will be automatically wired up as long as they don't
// have the [ExcludeFromAutoRegistrationAttribute].
//
// If you want to override a type that follows the convention, you should add the name
// of either the implementation name or the interface that it inherits to this list and
// add your manual registration code below. This will prevent duplicate registrations
// of the types from occurring.
// Example:
// typeof(SiteMap),
// typeof(SiteMapNodeVisibilityProviderStrategy)
// Add these 2 lines...
typeof(MvcContextFactory),
typeof(AuthorizeAttributeAclModule)
};
/// Other registration code here...
// Multiple implementations of strategy based extension points (and not decorated with [ExcludeFromAutoRegistrationAttribute]).
CommonConventions.RegisterAllImplementationsOfInterface(
(interfaceType, implementationType) => this.For(interfaceType).Singleton().Use(implementationType),
multipleImplementationTypes,
allAssemblies,
excludeTypes,
string.Empty);
// Add this line ...
this.for<IMvcContextFactory>().Use<MvcContextFactory2>();
/// Other registration code here...
// Configure Security
this.For<IAclModule>().Use<CompositeAclModule>()
.EnumerableOf<IAclModule>().Contains(x =>
{
// Change this line...
x.Type<AuthorizeAttributeAclModule2>();
//x.Type<XmlRolesAclModule>();
}); It turns out there is a bug in the Your other option is just to configure another route, and then your code will work like you have it. public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Add this route
routes.MapRoute(
name: "Test",
url: "Test/{action}/{method}",
defaults: new { controller = "Test" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
} |
Yes, it works so (and titles are not mixed). QueryString is ok for me. I prefer override AuthorizeCore and ValueProvider is not available here. I am thinking about routes in attributes. Route config is too far from actions. |
Well, attribute routes just get registered as routes in the end, so they work exactly the same way. You will need either upgrade to MVC5 or use the open source attribute routing to use them, though. We officially support the MVC5 attribute routing. I have not tested the open source project, but haven't had a single person complain about issues with it. |
…Node, Uri, TextWriter) overload was incorrectly adding the query string with the ? separator, which was interpreted by the QueryString dictionary as being part of the first key.
AuthorizeAttributeAclModule creates httpcontext from RouteData. This does not include querystring route parameters. So my custom authorizeattribute does not gets the parameters.
Values in filterContext.Controller.ValueProvider differs on normal security check and on security trimming check.
The text was updated successfully, but these errors were encountered: