MVC5 AntiForgeryToken - how to handle “The provided anti-forgery token was meant for user ”“, but the current user is ”xxx“.” exception?

半腔热情 提交于 2019-12-04 23:10:19

Try setting (in global.cs):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

This will add the name identifier to your token,

As for the double login issue try to use a script to document the date and time of the original submit to stop a second submit with the same token.

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
  $(this).on('submit',function(e){
    var $form = $(this);

    if ($form.data('submitted') === true) {
      // Previously submitted - don't submit again
      e.preventDefault();
    } else {
      // Mark it so that the next submit can be ignored
      $form.data('submitted', true);
    }
  });

  // Keep chainability
  return this;
};

So we know one thing; users like the back button and have a habit of the double click, this is a big issue with AntiforgeryToken.

But depending on what your application does there are ways to limit their compulsion to do so. The simplest of which is to do your best to try and make the visitor not feel like they need to “rewind” their request to alter it.

Ensure that form error messaging is clear and concise to ensure the user knows what is wrong. Contexual errors give bonus points.

Always maintain form state between form submissions. Apart from passwords or credit card numbers, there’s no excuse thanks the to MVC form helpers. @Html.LabelFor(x => x.FirstName)

If forms are spread across tabs or hidden divs such as those used in SPA frameworks like Angular or ember.js, be smart and show the controller layouts or form that the errors actually originated from in the form submission when displaying the error. Don’t just direct them to the home controller or first tab.

“What’s going on?” - Keeping the user informed

When a AntiForgeryToken doesn’t validate your website will throw an Exception of type System.Web.Mvc.HttpAntiForgeryException.

If you’ve set up correctly you’ve got friendly errors turned on and this will mean your error page will not show an Exception and show a nice error page that tells them what is up.

You can make this a little easier by at least giving the user a more informative page targeted at these exceptions by catching the HttpAntiForgeryException.

private void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();

    if (ex is HttpAntiForgeryException)
    {
        Response.Clear();
        Server.ClearError(); //make sure you log the exception first
        Response.Redirect("/error/antiforgery", true);
    }
}

and your /error/antiforgery view can tell them Sorry you have tried to submit the same information twice

Another Idea is to log the error and return the user to the login screen:

Create a HandleAntiforgeryTokenErrorAttribute class that Overrides the OnException method.

HandleAntiforgeryTokenErrorAttribute.cs:

public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary(new { action = "Login", controller = "Account" }));
    }
}

Global Filter:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new HandleAntiforgeryTokenErrorAttribute()
            { ExceptionType = typeof(HttpAntiForgeryException) }
        );
    }
}

I would also use a few tools to record all your information as login is critical part of your application

NLog for general logging and emails on critical application exceptions (including web exceptions).

Elmah for filtering and email of web exceptions.

EDIT: Also you may want to look at a jQuery plugin called SafeForm. Link

EDIT:

I have seen allot of debate on this and everyone's views on the subject have valid points, How i look at it is (Taken from owasp.org)

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated, CSRF attacks specifically target state-changing requests, not theft of data. The anti-forgery token is specific to 'who is logged on'. So once you login, then go back, the old token is no longer valid

Now i also use authorized IP addresses for login to allot of my applications with 2 factor authorization if the users IP address changes, so if Cross-Site Request Forgery was in play the user wouldn't match the IP address and request 2 factor authorization. almost like the way a security router would work. but if you want to keep it on your login page i don't see a problem as long as you have your friendly error pages set up people will not get upset as they will see they did something wrong.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!