I am writing an ASP.NET MVC 2.0 application which requires users to log in before placing a bid on an item. I am using an actionfilter to ensure that the user is logged in and, if not, send them to a login page and set the return url. Below is the code i use in my action filter.
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn","?ReturnUrl=",filterContext.HttpContext.Request.RawUrl));
return;
}
In my logon controller I validate the users credentials then sign them in and redirect to the return url
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
My problem is that this will always use a Get (HttpGet) request whereas my original submission was a post (HttpPost) and should always be a post. Can anyone suggest a way of passing this URL including the HttpMethod or any workaround to ensure that the correct HttpMethod is used?
There's no easy way to do this. What I would recommend you is to redirect the unauthenticated users to the login page not when posting to some URL but when requesting the form that will POST to the authenticated URL.
If you know that the form you are presenting to an unauthenticated user will POST to an authenticated part of the site, well, don't present him the form. When this form is requested simply redirect to the login page for authentication and once authenticated redirect to the original form. This way you will ensure that only authenticated users will POST to the protected resource.
As far as automated POST requests are concerned (bots, web services, ...) returning a simple 401 status code to requests that do not provide credentials should be more than sufficient.
I think I get why you want the authentication to only be on the bid POST
action. A bid requires login, but any non-logged in user can see the auction page. Just like ebay/amazon etc. Everything is visible until you require payment or action based on a user.
You could change your attribute to instead return the Request.UrlReferrer
to the login page if the Request.RequestType
is a POST
. Then they would be redirected to the auction page and can click bid again once they are logged in. You could even pass along a certain field, say amount, with the UrlReferrer
so that you could re-populate the amount field once they land on the auction page. You could get that field from the Request.Form
collection.
// in usage...
[RequireLogin(AdditionalFields="amount,someotherfield")]
[HttpPost]
public ActionResult Bid(.....)
// the attribute
class RequireLoginAttribute : ActionFilterAttribute
{
public string AdditionalFields { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var returnUrl = filterContext.HttpContext.Request.RawUrl;
if (filterContext.HttpContext.Request.RequestType == "POST")
{
returnUrl = filterContext.HttpContext.Request.UrlReferrer.PathAndQuery;
// look for FORM values in request to append to the returnUrl
// this can be helpful for a good user experience (remembering checkboxes/text fields etc)
}
filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn", "?ReturnUrl=", returnUrl));
return;
}
base.OnActionExecuting(filterContext);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With