I would like to protect my public method from being called by a user.
Because I'm calling the action from an ajax script I can't use any access modifiers, (private, protected etc).
Also, [HttpPost] doesn't stop the user from doing a fake request.
Anyone got a solution?
Thanks
Create an action filter that allows action methods to be called by AJAX only
namespace MyFilters
{
[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);
}
}
}
}
Then apply this to the action method
[AjaxOnly]
public JsonResult DoSomething()
{
....
Related
I commonly need to authorize a particular parameter to be evaluated in a service call within an action in MVC5. For instance, let's say that my action is public ActionResult Edit(string partnerName).
Today, I handle this by always evaluating if (!User.CanAccessPartnerModule(THIS_MODULE_ID, partnerName)) throw new UnauthorizedException();
However, I would like to be able to do something like this:
[Authorize(Roles = THIS_MODULE_ID)]
public ActionResult Edit([AuthorizePartnerModule(THIS_MODULE_ID)] string partnerName)
{
...
}
To be clear, 1) I don't think the AuthorizeAttribute would be necessary if this were implemented as I envision, and 2) the thing that doesn't exist is the AuthorizePartnerModuleAttribute.
Is there a ready-made attribute or tutorial that explains how this may be accomplished? And if not, is this not advisable to do?
You could extend authorization with a custom authorization filter by creating a subclass of AuthorizeAttribute
using System.Web;
using System.Web.Mvc;
namespace Filters
{
public class AuthorizePartnerModule : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// getting the parameter from the request
string partnerName = httpContext.Request.Params["groupId"].ToString();
// custom validation
return User.CanAccessPartnerModule(THIS_MODULE_ID, partnerName);
}
}
}
And then, you could validate your action method with:
[AuthorizePartnerModule(Roles = THIS_MODULE_ID)]
public ActionResult Edit(string partnerName)
{
...
}
Another option would be to create a custom ActionFilter (an implementation of IActionFilter). An ActionFilter implements two methods:
OnActionExecuting is executed right before the action method
OnActionExecuted is executed right after the action method execution.
So, you could make the necessary validation with something like:
using System.Web.Mvc;
namespace Filters {
public class AuthorizePartnerModule : FilterAttribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
// getting the parameter from the request
string partnerName = filterContext.ActionParameters["partnerName"].ToString();
// custom validation
if (!User.CanAccessPartnerModule(THIS_MODULE_ID, partnerName))
{
filterContext.Result = new HttpNotFoundResult();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// do nothing
}
}
}
In this case, however ,you would have to validate like that:
[Authorize(Roles = THIS_MODULE_ID)]
[AuthorizePartnerModule]
public ActionResult Edit(string partnerName)
{
...
}
I have a scenario i need to check security for each menu item if user 'A' is allowed to access this menu or not and for that reason i created a class which is inherited with ActionFilterAttribute
public class SecurityFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
}
and using this class on my controller
[SecurityFilter]
public class XYZController : Controller
{
public ActionResult Index() {
return View();
}
}
Now the problem is in my View i have #Html.Action() calls e.g
#Html.Action("COM")
which results in calling onActionExecuting Method again, i Just want it to call it one time when menu link is clicked and for that method only where menu is redirecting not the other Action method which is render inside view
When called using #Html.Action the IsChildAction property of the filterContext will be true. You can rely on it to determine whether you actually want to do something or not:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.IsChildAction)
return;
Log("OnActionExecuting", filterContext.RouteData);
}
See MSDN
Say I have a controller with multiple actions, is there an override to make the controller return a default action if a condition is met?
Example:
I have a checkoutcontroller and I want each action to return HttpNotFound() if e-commerce is disabled on the site, is there a better way of doing it than just doing the following:
public class CheckoutController
{
[HttpGet]
public ActionResult ViewBasket()
{
if (AppSettings.EcommerceEnabled)
{
return View();
}
else
{
return HttpNotFound();
}
}
[HttpGet]
public ActionResult DeliveryAddress()
{
if (AppSettings.EcommerceEnabled)
{
return View();
}
else
{
return HttpNotFound();
}
}
}
You can create a custom action filter that will be used for action methods inside CheckoutController.
public class CommercePermissionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (AppSettings.EcommerceEnabled)
{
base.OnActionExecuting(filterContext);
}
else
{
// Example for redirection
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "Controller", "Error" },
{ "Action", "AccessDenied" }
});
}
}
}
Then you can use this filter on each action method by
[HttpGet]
[CommercePermission]
public ActionResult ViewBasket()
Or if you want whole controller actions to have this filter,
[CommercePermission]
public class CheckoutController
You can even apply filters globally to all actions in your project.
You can find more info here.
You could create a custom action filter. This would intercept the routing to that action, apply its internal logic, and either continue to the action or interrupt it as you define in the filter. Filters can be applied to individual actions, an entire controller class, or even globally for the whole application.
I want to centralize authentication that developers are free to worry about the implementation of security.
I dont want to validate the authentication at each request like
public class HomeController : BaseController
{
public ActionResult Home()
{
if (Request.IsAuthenticated == true)
{
return RedirectToAction("Home", "Member");
}
return View();
}
public ActionResult Resources()
{
if (Request.IsAuthenticated == true)
{
return RedirectToAction("Resources", "Member");
}
return View();
}
}
Thanks
You can centralized your credential validation by using a BaseController for all your controller inside your application
public class BaseSupplierFlyersController : BaseController
{
//
// GET: /SupplierFlyers/
public ActionResult Index(string culture)
{
//Some action logic here
return View("Index");
}
}
In your BaseControler
public class BaseController : Controller
{
private bool IsLoged = false;
public BaseController()
: base()
{
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!IsLoged)
{
//Redirection du bad login.
//Affect the Result to cancelled previous Action execution
filterContext.Result = new RedirectResult(string.Concat("~/", ControllerConstants.Error,"/", ActionConstants.BadLogin));
}
base.OnActionExecuting(filterContext);
}
protected override void Execute(RequestContext requestContext)
{
//Validate Credential
ValidateCredential(requestContext);
//Traitement standard
base.Execute(requestContext);
}
private void ValidateCredential(RequestContext requestContext)
{
//Logic to validate credential here
IsLoged = true; //or false
}
}
Each time an Action from a Controller is fired the BaseController will validate credential in Execute method and in OnActionExecuting you can valide if the credential are valid and than take an Action like Redirect to an other page.
Looking at the code you wrote it seems like you are missing Action Filters that are part of asp.net mvc. There is one built in called Authorize that basically requires a request to be authenticated before the controller method is invoked, but creating your own is very simple.
Also in asp.net mvc 3 you can define global filters which will be part of every action invoked on your controllers. You can find some samples here
How do I use the ASP.NET MVC 2 Preview 2 Futures RequireHttps attribute?
I want to prevent unsecured HTTP requests from being sent to an action method. I want to automatically redirect to HTTPS.
MSDN:
RequireHttpsAttribute
RequireHttpsAttribute Members
RequireHttpsAttribute.HandleNonHttpsRequest Method
How do I use this feature?
I think you're going to need to roll your own ActionFilterAttribute for that.
public class RedirectHttps : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!filterContext.HttpContext.Request.IsSecureConnection) {
filterContext.Result =
new RedirectResult(filterContext.HttpContext.Request.Url.
ToString().Replace("http:", "https:"));
filterContext.Result.ExecuteResult(filterContext);
}
base.OnActionExecuting(filterContext);
}
}
Then in your controller :
public class HomeController : Controller {
[RedirectHttps]
public ActionResult SecuredAction() {
return View();
}
}
You might want to read this as well.
My guess:
[RequireHttps] //apply to all actions in controller
public class SomeController
{
//... or ...
[RequireHttps] //apply to this action only
public ActionResult SomeAction()
{
}
}