Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

c# - A way of properly handling HttpAntiForgeryException in MVC 4 application

Here is the scenario:

I have a login page, when user sign it it is redirected to home application page. Then user is using browser back button, and now he is on login page. He tries to login again but now an exception is thrown:

HttpAntiForgeryException (0x80004005): The provided anti-forgery token was meant for user "", but the current user is "userName".

I know this is related to caching. I disabled browser caching for login action using custom NoCache filter which sets all required headers - no-cache, no-store, must-revalidate, etc. But

  • this is not working on all browsers
  • especially Safari (mobile in most cases) totaly ignores such settings

I will try to make hacks and force safari mobile to refresh, but this is not what I'm expecting.

I would like to know if I can:

  • handle exception without showing user any problem exists (totally transparent for user)
  • prevent this problem by replacing anti forgery token user name which will allow user login again without this exception, if my hacks related to browser caching will stop work in next versions of browsers.
  • I really would like not to rely on browser behavior, since each one behaves differently.

UPDATE 1

To make some clarification, I know how to handle errors in MVC. The problem is that this handling errors is not solving my problem at all. Basic idea of error handling is redirect to custom error page with nice message. But I want to prevent this error to happen, not to handle it in user visible way. By handle I mean catch make username replace or other suitable action then continue login.

UPDATE 2

I've added below solution which is working for me.

question from:https://stackoverflow.com/questions/12967917/a-way-of-properly-handling-httpantiforgeryexception-in-mvc-4-application

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

After some time of investigation I think I found some way how to get rid of this error for user. It is not perfect but at least not display error page:

I created filter based on HandleErrorAttribute:

    [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", 
        Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class LoginAntiforgeryHandleErrorAttribute : FilterAttribute, IExceptionFilter
    {
        #region Implemented Interfaces

        #region IExceptionFilter

        /// <summary>
        /// </summary>
        /// <param name="filterContext">
        /// The filter context.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// </exception>
        public virtual void OnException(ExceptionContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (filterContext.IsChildAction)
            {
                return;
            }

            // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            {
                return;
            }

            Exception exception = filterContext.Exception;

            // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
            // ignore it.
            if (new HttpException(null, exception).GetHttpCode() != 500)
            {
                return;
            }

            // check if antiforgery
            if (!(exception is HttpAntiForgeryException))
            {
                return;
            }

            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "action", "Index" }, 
                    { "controller", "Home" }
                });

            filterContext.ExceptionHandled = true;
        }

        #endregion

        #endregion
    }

Then I applied this filter to Login POST action:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[LoginAntiforgeryHandleError]
public ActionResult Login(Login model, string returnUrl)
{

The main idea of this solution is to redirect anti-forgery exception to main index action. If user will still won't be unauthenticated it will show then login page if user will be already authenticated it will show index page.

UPDATE 1 There is one potential problem with this solution. If somebody is logging in with different credentials then on error it should be added additional login runtime - logout previous user and login new one. This scenario is not handled.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...