Is there a simple way to apply a filter on action methods in ASP.NET MVC3 against specific types of UserAgents? I have a hacking network chewing on us in different ways. I can play cat and mouse with IPs, subnets, etc at the network/firewall level but would like to inject an app level assurance against things like Squid, etc as they appear to have certain patterns that arise. Not sure how this would affect performance but wondered if anyone has done this approach.
thanks in advance.
doug
You would have to create a custom action filter. Here is an example of one that returns an http 403 forbidden if the requesting user agent is a mozilla-based browser:
public class UserAgentActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.UserAgent.ToLowerInvariant().Contains("mozilla"))
{
filterContext.Result = new HttpStatusCodeResult(403);
}
base.OnActionExecuting(filterContext);
}
}
Just remember that user-agents can be faked if they realize that is how they are being blocked.
Related
I understand different types of filters are available in ASP.NET MVC. Now I am confused about the following 3 types of filters. I have to use custom filters in my code.
Authentication Filter
Authorization Filter
Action Filter
I have users, roles and their permissions (read, add, delete) in 4 different tables.
Which filter method I should choose?
When I did a search, I am able to found some of them using Action filters as
public class MyFirstCustomFilter : ActionFilterAttribute
{
....
}
OnActionExecuting - my code goes here for role and permmsion - is this correct way ?
OnResultExecuting
But some article use
public class CustomAuthAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
//my code goes here for role and permission check - is this correct way ?
}
}
I want to check user is eligible to execute particular action based on roles & permission in db.
Now I am confused with all these methods. For me, all are similar. Correct me if I am wrong.
I'm looking for a better logging approach for a large MVC project. I tried to look around towards other's suggestions (like Log4Net, Nlog, ELMAH, EntityFramework's Self tracking & few others), but could not find reasonable answer. By term logging i don't simply mean logging few requests or exceptions etc. But log for every little change in properties. That's the reason I'm looking for some perfect (generic) approach, which can be used for several applications. I need to roughly log as:
public class someModelPerson
{
public string Name { get; set; }
public string Age { get; set; }
}
If through some action, the current object of someModelPerson is updated, I need to log at the end of the method as:
Property Name changed from 'John' to 'Don' by user 'xyz' on 12/12/12
I worked with EntityFramework selftracking and implemented something similar and generic (using templates etc) but it's no more recommended by Microsoft.
I'm okay if the solution requires a little customization accordingly.
plus do suggest the better DB schema for storing log of single model modifications. (like update_person method may change name, age, height of a person. How should it be logged at DB level? single entry? separate table for changeset?)
you can use Postsharp as stated in website :-
PostSharp offers a solution to all of these problems. The logging
pattern library allows you to configure where logging should be
performed and the pattern library takes over the task of keeping your
log entries in sync as you add, remove and refactor your codebase.
Let's take a look at how you can add trace logging for the start and
completion of method calls.
For more information take a look here :-
http://www.postsharp.net/diagnostics/net-logging
public class LoggingFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +
filterContext.ActionDescriptor.ActionName);
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception != null)
filterContext.HttpContext.Trace.Write("(Logging Filter)Exception thrown");
base.OnActionExecuted(filterContext);
}
}
I just wanted to gauge opinions on how I should approach this problem and ultimately looking for a quick win (wrong way to think about things nut time pressures mean I have to think and act quickly!
I've been given a website that has a bit of an issue.
I login using standard forms authentication as User1234 and my url is as follows:
www.mywebsite.co.uk/1234/Contact.
This will take me to User1234's details.
You can put two and two together and correctly assume that 1234 is a user id of some sort.
Once authenticated, I can access the views with [Authorize] attribute present, any anonymous/unathenticated users get redirected.
However, once logged in as User1234, I can then tinker with the url like so:
www.mywebsite.co.uk/1235/Contact.
So I am authenticated as User1234 but can see User1235's data. This is BAD for obvious reasons.
When I log in, I actively set the login ID in session so in theory, I could do a check whenever a user hits an ActionResult, I could cross check the ID present in the URL against the session login ID. However, it is a rather project with lots of action results and as such, I'm reluctant to spend my Saturday afternoon adding something to each and every ActionResult.
Is there an event in the global.asax I could use that is hit on each ActionResult request where I can compare Session login ID with url ID?
Alternatively, can anyone offer some suggestions about how I can achieve this or restrict URL tampering?
You can try and do a base controller
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Do your stuff here
base.OnActionExecuted(filterContext);
}
}
I assume that you don't want to change your URL routes, as you could retrieve the user id also from the session. A quick solution would be to use an ActionFilter which you can place on the affected controllers or action methods:
public class VerifyUserIdAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var sessionUserId = filterContext.HttpContext.Session["UserId"];
var routeUserId = filterContext.RouteData.Values["UserId"];
if (routeUserId != null && sessionUserId == routeUserId)
filterContext.Result = new RedirectResult("<<url to redirect to>>");
}
}
I don't understand why the URL contains a data entry point. This appears to be a design flaw. I would remove all code that uses a URL parameter and instead make sure the controller looks up what the ID is based on the logged in user.
I want to keep a log of all the requests to my MVC 3 app, including requested URL, user's ip adress, user agent, etc. Where is the best place to do this,
1) use a base controller?
2) use an action filter?
3) others?
I do this inside my BaseController. Something like this:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// If in Debug mode...
if (filterContext.HttpContext.IsDebuggingEnabled)
{
var message = string.Format(CultureInfo.InvariantCulture,
"Leaving {0}.{1} => {2}",
filterContext.Controller.GetType().Name,
filterContext.ActionDescriptor.ActionName.Trim(),
filterContext.Result);
Logger.Debug(message);
}
// Logs error no matter what
if (filterContext.Exception != null)
{
var message = string.Format(CultureInfo.InvariantCulture,
"Exception occured {0}.{1} => {2}",
filterContext.Controller.GetType().Name,
filterContext.ActionDescriptor.ActionName.Trim(),
filterContext.Exception.Message);
Logger.Error(message);
}
base.OnActionExecuted(filterContext);
}
Hope you get the idea.
You can also log before the action is executed using:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
An HttpModule seems like the best fit, if you ask me.
All of the data you're talking about logging is available well before any particular Controller gets invoked. So if you do logging outside of the controller, then you get to capture even those requests which are not to valid controller actions. And there's no need to clutter your controller code with something that's really a cross-cutting concern.
You can have multiple action methods triggered when rendering a single request. Consider using RenderAction on your layout page as follows:
Html.RenderAction("Navigation", "Menu")
It's worth noting that you'd then have two log entries with the same information if you choose to use action filter for logging.
I´m have a Car View with a list of car... So, I have a Create button that opens a Modal (UI JQuery Dialog) with Site/Car/Create content...
All works fine... But I´d like to block direct access to : Site/Car/Create...
Is that possible? How?
Thanks
It's not really possible to block it completely, but you can do some things to make it more difficult. First, require that it come from a POST request. That will prevent someone from simply entering the URL with request parameters. Second, use the antiforgery token helper. That will help prevent a third-party from doing a POST to the url since they will also require both the token input and the token cookie. Third, you could potentially check if the request has the X-HTTP-REQUESTED-WITH header and only do the POST (or GET) via AJAX. It's not that hard to get around but it would prevent an accidental access if you do use GET. Fourth, and it probably should have been first, make sure that only authorized users have access to the action using the AuthorizeAttribute. Fifth, use SSL to prevent unauthorized access using FireSheep and protect your cookies and data from snooping.
In short, you won't be able to prevent a determined person with legitimate authorization from crafting a request to the action if they a really want to without using your interface. They can always craft a request that will look exactly like the one you would send. You can make it more difficult and prevent accidental access, though, using the above methods.
[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 404;
filterContext.Result = new HttpNotFoundResult();
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
And then stick on your Create action like this:
[AjaxOnly]
public ActionResult Create()
{
...etc
}