Mvc3防伪标记多标签页

10

我们在登录页面的防伪标记上遇到了一个特定的问题。 如果用户仅使用一个活动窗口登录,则一切正常,但是如果用户在两个不同的窗口中打开登录页面并从窗口A登录(登录时没有问题),然后从窗口B返回登录,在此窗口中用户将收到“未提供或无效的必需防伪标记”。

除了从视图/控制器操作中删除防伪标记之外,是否有其他方法可以解决这个问题? 我们希望保留该标记以提高安全性!

这与此问题非常相似,但是这是针对mvc2提出的问题: MVC ValidateAntiForgeryToken multi-tabs problem


我给你留了另一个答案 - 我应该回答自己的问题! - Dave Bish
2个回答

27

MVC3或MVC4中的这种行为是按设计进行的,但正如上面所解释的那样,它非常不友好。然而,在生产环境中,需要优雅地解决此问题并处理这种奇怪的情况。解决此问题的方法是创建一个过滤器属性,应用于登录后的验证,以验证用户是否已登录,并将他们带到正确的页面,否则他们将继续停留在登录页面。

下面是过滤器属性的代码

/// <summary>
/// Handle Antiforgery token exception and redirect to customer area if the user is Authenticated
/// </summary>
public class RedirectOnError : HandleErrorAttribute
{
    /// <summary>
    /// Override the on exception method and check if the user is authenticated and redirect the user 
    /// to the customer service index otherwise continue with the base implamentation
    /// </summary>
    /// <param name="filterContext">Current Exception Context of the request</param>
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.Exception is HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            // Set response code back to normal
            filterContext.HttpContext.Response.StatusCode = 200;

            // Handle the exception
            filterContext.ExceptionHandled = true;

            UrlHelper urlH = new UrlHelper(filterContext.HttpContext.Request.RequestContext);

            // Create a new request context
            RequestContext rc = new RequestContext(filterContext.HttpContext, filterContext.RouteData);

            // Create a new return url
            string url = RouteTable.Routes.GetVirtualPath(rc, new RouteValueDictionary(new { Controller = "CustomerArea", action = "Index" })).VirtualPath;

            // Check if there is a request url
            if (filterContext.HttpContext.Request.Params["ReturnUrl"] != null && urlH.IsLocalUrl(filterContext.HttpContext.Request.Params["ReturnUrl"]))
            {
                url = filterContext.HttpContext.Request.Params["ReturnUrl"];
            }

            // Redirect the user back to the customer service index page
            filterContext.HttpContext.Response.Redirect(url, true);
        }
        else
        {
            // Continue to the base
            base.OnException(filterContext);
        }
    }
}

这是一个使用示例

        [HttpPost]
        **[RedirectOnError]**
        [ValidateAntiForgeryToken]
        public ActionResult LogOn(LogOnViewModel model, UserSessionState session, string returnUrl)
        {
        .....
        }

我不明白如果用户没有登录会发生什么...因为留在登录页面可能会再次导致异常。 - ilans
2
回复 IlanS - 代码 如果 (filterContext.Exception is HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated) 只有在用户已登录时才会应用重定向,否则将抛出非经过身份验证的用户的常规异常。 - MORCHARD

4

一旦您登录,所有先前的令牌都无效。这就是它应该工作的方式。Naz接近了正确的答案,但是cookie中的令牌并没有存储用户名。只有表单中的令牌才存储。正是因为这个问题:如果用户登录,所有现有的表单令牌应该被使无效,但是使cookie本身无效将会过于棘手和不友好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接