2015-09-18 14 views
8

Tôi muốn bảo vệ hành động đăng nhập của chúng tôi bằng cách AntiforgeryToken thuộc tính - Tôi biết lý do ngoại lệ từ chủ đề xảy ra, tuy nhiên tôi dường như không tìm được giải pháp nào tốt cho nó.MVC5 AntiForgeryToken - cách xử lý "Mã thông báo chống giả mạo được cung cấp có nghĩa là dành cho người dùng" ", nhưng người dùng hiện tại là" xxx "." ngoại lệ?

Hãy nói rằng chúng ta có những tình huống sau:

  1. Nó 08:00, người dùng ứng dụng đang đến để làm việc, họ ngồi xuống và bắt đầu quá trình đăng nhập - ngay bây giờ nó là rất có thể rằng một số người dùng sẽ nhận được cùng một ValidationToken. Sau khi người đầu tiên đăng nhập - tất cả những người khác sẽ thấy ngoại lệ trên (hoặc một số màn hình ngoại lệ tùy chỉnh khác) khi họ cố đăng nhập.

  2. Một số người dùng đã đăng nhập, sau đó vô tình nhấn nút "quay lại" và cố đăng nhập lại - trong khi điều này khó xảy ra .

Vậy câu hỏi rất đơn giản - làm thế nào để ngăn chặn những tình huống trên, hoặc làm thế nào để xử lý chúng để người dùng sẽ không nhận thấy bất cứ điều gì. Tôi đã thử các cách sau:

  1. Đặt AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; trong Application_Start trong Global.asax - nó không khắc phục được vấn đề, tôi vẫn nhận được cùng một ngoại lệ
  2. Thiết lập [OutputCache (NoStore = true, Thời gian = 0, VaryByParam = "Không")] vào phương pháp với [ValidateAntiForgeryToken] thuộc tính - một lần nữa, không may mắn có

Ngay bây giờ tôi đã suy nghĩ để tay xác nhận token trong cơ thể hành động, bắt lỗi, và kiểm tra nếu cố gắng được thực hiện bởi người dùng ẩn danh:

public ActionResult SomeAction() 
{ 
    try 
    { 
     AntiForgery.Validate(); 
    } 
    catch(HttpAntiForgeryException ex) 
    { 
     if(String.IsNullOrEmpty(HttpContext.User.Identity.Name)) 
     { 
      throw; 
     } 
    } 

    //Rest of action body here 
    //.. 
    //.. 
} 

Ở trên dường như để ngăn chặn lỗi - nhưng có an toàn không?Có những lựa chọn thay thế nào?

Xin cảm ơn trước.

Trân trọng.

EDIT:

Trận chung kết "Giải pháp" là để vô hiệu hóa xác nhận thẻ vào mẫu đăng nhập - có thể có một cách tốt hơn để xử lý nó, nhưng có vẻ như tất cả các giải pháp tôi thấy, là cách giải quyết xấu xí tương tự như tôi đề xuất ở trên.

Vì không có cách nào để biết cách "an toàn" các lựa chọn thay thế này (nếu chúng an toàn), chúng tôi quyết định thực hiện xác thực mã thông báo vô hiệu hóa khi đăng nhập.

+0

Bạn có thể sử dụng tập lệnh để tắt gửi hai lần, http://stackoverflow.com/questions/2830542/prevent-double-submission-of-forms-in-jquery –

+0

Xin chào, tôi cũng gặp vấn đề tương tự khi người dùng nhấn nút quay lại trên trình duyệt. Bạn đã kết thúc bằng cái gì? – VAAA

+0

@VAAA: Xem phần EDIT của câu hỏi của tôi - vì chỉ có biểu mẫu đăng nhập đã cho chúng tôi vấn đề này, cuối cùng, chúng tôi vừa tắt xác thực mã thông báo ở đó. Chúng tôi quyết định đơn giản là không đáng để giải quyết rắc rối và thẳng thắn, tôi không thể tìm thấy giải pháp 'sạch' nào - chỉ có một số cách giải quyết xấu (giống như giải pháp mà tôi đã đăng với bản thử). – user2384366

Trả lời

7

Thử cài đặt (trong toàn cầu.cs):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 

này sẽ bổ sung các định danh tên vào mã thông báo của bạn,

Đối với các vấn đề đăng nhập đôi cố gắng sử dụng một kịch bản để ghi lại ngày và thời gian của bản gốc nộp để ngăn chặn một trình thứ hai với cùng một mã thông báo.

// 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; 
}; 

Vì vậy, chúng tôi biết một điều; người dùng thích nút quay lại và có thói quen nhấp đúp, đây là vấn đề lớn với AntiforgeryToken.

Nhưng tùy thuộc vào ứng dụng của bạn có những cách nào để hạn chế buộc phải làm như vậy. Cách đơn giản nhất là cố gắng hết sức để làm cho khách truy cập không cảm thấy họ cần phải “tua lại” yêu cầu của họ để thay đổi nó.

Đảm bảo rằng thông báo lỗi biểu mẫu rõ ràng và súc tích để đảm bảo người dùng biết điều gì là sai. Lỗi theo ngữ cảnh cho điểm thưởng.

Luôn duy trì trạng thái biểu mẫu giữa các lần gửi biểu mẫu. Ngoài số điện thoại mật khẩu hoặc số thẻ tín dụng, không có lý do gì để cảm ơn người giúp việc mẫu MVC . @Html.LabelFor(x => x.FirstName)

Nếu hình thức được lan truyền trên các tab hoặc divs ẩn như những người sử dụng trong khuôn khổ SPA như kiễu góc hoặc ember.js, hãy thông minh và hiển thị các bố trí điều khiển hoặc hình rằng lỗi thực sự có nguồn gốc từ trong nộp mẫu đơn khi hiển thị lỗi. Không chỉ hướng họ tới bộ điều khiển chính hoặc tab đầu tiên.

“Những gì đang xảy ra?” - Giữ người dùng thông báo

Khi một AntiForgeryToken không xác nhận trang web của bạn sẽ ném một ngoại lệ kiểu System.Web.Mvc.HttpAntiForgeryException.

Nếu bạn đã thiết lập chính xác bạn đã gặp lỗi thân thiện và điều này có nghĩa là trang lỗi của bạn sẽ không hiển thị Ngoại lệ và hiển thị trang lỗi đẹp cho biết điều gì đang xảy ra.

Bạn có thể làm điều này dễ dàng hơn một chút bằng cách ít nhất là cung cấp cho người dùng một trang thông tin hơn được nhắm mục tiêu tại các ngoại lệ này bằng cách bắt 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); 
    } 
} 

/error/antiforgery xem của bạn có thể nói với họ Xin lỗi bạn đã cố gắng gửi thông tin cùng một hai lần

Idea khác là để ghi lại các lỗi và trả lại người dùng đến màn hình đăng nhập:

Tạo một lớp HandleAntiforgeryTokenErrorAttribute ghi đè phương thức OnException.

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" })); 
    } 
} 

toàn cầu Lọc:

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

Tôi cũng sẽ sử dụng một vài công cụ để ghi lại tất cả thông tin của bạn như đăng nhập là một phần quan trọng của ứng dụng của bạn

NLog cho khai thác gỗ nói chung và email về ngoại lệ ứng dụng quan trọng (bao gồm ngoại lệ trên web).

Elmah để lọc và email ngoại lệ web.

CHỈNH SỬA: Ngoài ra, bạn có thể muốn xem một plugin jQuery có tên là SafeForm. Link

EDIT:

Tôi đã thấy phân bổ cho các cuộc tranh luận về vấn đề này và quan điểm của mọi người về đề tài này có điểm hợp lệ, Làm thế nào tôi nhìn vào nó được (Trích từ owasp.org)

chéo Giả mạo yêu cầu trang web (CSRF) là một cuộc tấn công buộc người dùng cuối thực thi các hành động không mong muốn trên ứng dụng web trong đó họ đang hiện được xác thực, các cuộc tấn công CSRF nhắm mục tiêu cụ thể g yêu cầu, không bị đánh cắp dữ liệu. Mã thông báo chống giả mạo là dành riêng cho 'người đã đăng nhập'. Vì vậy, một khi bạn đăng nhập, sau đó quay trở lại, các thẻ cũ không còn giá trị

Bây giờ tôi cũng sử dụng địa chỉ IP có thẩm quyền để đăng nhập vào phân phối các ứng dụng của tôi với 2 phép nhân tố nếu người sử dụng địa chỉ IP thay đổi, vì vậy nếu Yêu cầu qua trang web giả mạo đã được thực hiện khi người dùng không khớp với địa chỉ IP và yêu cầu ủy quyền 2 yếu tố. gần giống như cách một bộ định tuyến bảo mật hoạt động. nhưng nếu bạn muốn giữ nó trên trang đăng nhập của bạn, tôi không thấy một vấn đề miễn là bạn có các trang lỗi thân thiện của bạn thiết lập mọi người sẽ không nhận được khó chịu vì họ sẽ thấy họ đã làm điều gì đó sai trái.

+0

Cảm ơn bạn đã trả lời và xin lỗi vì phản hồi muộn - tôi sửa đổi giải pháp của bạn một chút (tôi sử dụng trường nhập ẩn để vượt qua: "đã được gửi" giá trị) và bây giờ tình trạng "nút quay lại" dường như được giải quyết, tuy nhiên tình hình từ AD1 vẫn tồn tại, điều này có thể được mô phỏng bằng cách tải, biểu mẫu đăng nhập trong hai tab khác nhau trong trình duyệt, tôi có thể thấy rõ ràng rằng cookie "___RequestverificationToken" giống nhau cho cả hai tab và khi tôi gửi, tôi nhận được lỗi giống như trước đây. Trong khi tôi có thể bắt ngoại lệ này, tôi vẫn không phải làm gì với nó ... – user2384366

+0

Thật vậy Câu trả lời thực sự cho vấn đề này đơn giản là bạn không nên sử dụng mã thông báo chống giả mạo trên biểu mẫu đăng nhập! Thật vô nghĩa khi "giả mạo" là người dùng trên biểu mẫu đăng nhập - họ chưa đăng nhập và là người dùng ẩn danh cho đến khi họ đăng nhập!do đó, việc sử dụng người dùng ẩn danh để tạo Mã thông báo yêu cầu, mã thông báo chống giả mạo sẽ được sử dụng trên biểu mẫu sau khi người dùng đăng nhập, vì các tab trên cùng một trình duyệt và máy tính sẽ không có gì khác nhau giữa chúng. –

+1

Thành thật mà nói - Tôi hơi bối rối vào lúc này, bởi vì dường như có hai quan điểm khác biệt về chủ đề, ví dụ ở đây: http://security.stackexchange.com/questions/2120/when-the Tôi đã tìm thấy câu trả lời khá rộng rãi với ví dụ, tuyên bố rằng mã thông báo chống giả mạo nên được sử dụng trên biểu mẫu đăng nhập ... mặt khác có rất nhiều bài đăng khác trạng thái đó khác ... Tôi sẽ đợi thêm một số ý tưởng khác có thể - nhưng nếu không có gì, tôi đoán tôi sẽ làm như bạn đề xuất và vô hiệu hóa xác thực mã thông báo khi đăng nhập :) – user2384366

Các vấn đề liên quan