2013-05-07 26 views
18

Tôi có ứng dụng MVC 4 và gặp sự cố khi phiên biểu mẫu hết hạn và sau đó người dùng cố gắng đăng xuất.Khi đăng xuất, mã thông báo chống giả mạo được cung cấp cho người dùng "XXXX", nhưng người dùng hiện tại là ""

Ví dụ: thời gian chờ được đặt là 5 phút. Nhật ký người dùng. Người dùng không làm gì trong 10 phút. Người dùng nhấp vào liên kết Đăng xuất. Người dùng gặp lỗi: "Mã thông báo chống giả mạo được cung cấp dành cho người dùng" XXXX ", nhưng người dùng hiện tại là" "."

Người dùng sau đó phải trải qua một số môn thể dục dụng cụ để giải quyết vấn đề này để họ có thể đăng nhập lại sau đó đăng xuất lại (đăng xuất đang được sử dụng để đóng bảng thời gian cho ngày đó).

Tôi nghĩ rằng tôi hiểu tại sao điều này xảy ra ... nhưng không chắc chắn cách khắc phục.

EDIT: Tại sao tôi nghĩ điều này xảy ra là vì ban đầu khi trang được tải, mã thông báo AntiForgery được tạo cho người dùng hiện đã đăng nhập. Nhưng sau đó khi phiên hết hạn và họ cố gắng điều hướng đến trang đăng xuất, người dùng hiện tại là "" thay vì người dùng thực tế. Như vậy có sự không phù hợp và lỗi được hiển thị.

+0

Bạn có thể chia sẻ giả thuyết của bạn tại sao lỗi xảy ra? – J0e3gan

+0

Một [bài viết liên quan] (http://stackoverflow.com/questions/14970102/anti-forgery-token-is-meant-for-user-but-the-current-user-is-username) có giá trị xem xét. – J0e3gan

+0

Nhập giả thuyết của tôi. Tôi thấy bài viết mà bạn đã đề cập đến, và mặc dù nó có thể liên quan, tôi không thể kết nối các dấu chấm ... Tôi không thực sự quen thuộc với khía cạnh này của ASP.NET. –

Trả lời

22

Trên thực tế bạn có thể xử lý nó với IExceptionFilter, mà sẽ chuyển hướng đến /Account/Login

public class HandleAntiForgeryError : ActionFilterAttribute, IExceptionFilter 
{ 
    #region IExceptionFilter Members 

    public void OnException(ExceptionContext filterContext) 
    { 
     var exception = filterContext.Exception as HttpAntiForgeryException; 
     if (exception != null) 
     { 
      var routeValues = new RouteValueDictionary(); 
      routeValues["controller"] = "Account"; 
      routeValues["action"] = "Login"; 
      filterContext.Result = new RedirectToRouteResult(routeValues); 
      filterContext.ExceptionHandled = true; 
     } 
    } 

    #endregion 
} 

[HandleAntiForgeryError] 
[ValidateAntiForgeryToken] 
public ActionResult LogOff() 
{ 
} 

Ngoài ra bạn có thể sử dụng [HandleError(ExceptionType=typeof(HttpAntiForgeryException)...] nhưng nó đòi hỏi customErrors Bật.

+0

Tuyệt vời! Chỉ cần những gì tôi cần cảm ơn! –

+0

Tôi không thể tin rằng điều này chưa được đánh dấu là câu trả lời. Câu trả lời này thật đáng kinh ngạc. –

+1

Đối với những gì nó có giá trị, điều này không làm việc cho tôi. Khi tôi đăng xuất, các ứng dụng barfs trên cùng một lỗi. Tuy nhiên, loại ngoại lệ là InvalidOperationException thay vì HttpAntiforgeryException. Điều này là rất chung chung, làm cho nó nguy hiểm để xử lý này chỉ đơn giản là:/ – Sinaesthetic

2

Câu trả lời của @cem thực sự hữu ích đối với tôi và tôi đã thêm một thay đổi nhỏ để bao gồm trường hợp các cuộc gọi ajax có phiên antiforgerytoken và hết hạn.

public void OnException(ExceptionContext filterContext) 
{ 
    var exception = filterContext.Exception as HttpAntiForgeryException; 
    if (exception == null) return; 

    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    { 
     filterContext.HttpContext.Response.StatusCode = 403; 
     filterContext.ExceptionHandled = true; 
    } 
    else 
    { 
     var routeValues = new RouteValueDictionary 
     { 
      ["controller"] = "Account", 
      ["action"] = "Login" 
     }; 
     filterContext.Result = new RedirectToRouteResult(routeValues); 
     filterContext.ExceptionHandled = true; 
    } 
} 

... và ở phía khách hàng mà bạn có thể thêm một lỗi xử lý ajax toàn cầu để chuyển hướng đến màn hình đăng nhập ...

$.ajaxSetup({ 
    error: function (x) { 
     if (x.status === 403) { 
      window.location = "/Account/Login"; 
     } 
    } 
}); 
Các vấn đề liên quan