2017-10-11 69 views
5

Chúng tôi có một trang với nhiều hình thức. Mỗi phòng có @Html.AntiForgeryToken() riêng. Trên máy của tôi mọi thứ đều tuyệt vời.__RequestVerificationToken không phải lúc nào cũng được tạo

Chúng tôi đã triển khai Azure (PAAS), nhưng __RequestVerificationTokenkhông được tạo trên mọi yêu cầu. Đôi khi nó ở đó và đôi khi tôi nhận được Cookie chống giả mạo bắt buộc không có mặt và hiếm khi tôi nhận được mã thông báo không khớp với lỗi.

Tôi hoàn toàn không biết gì về điểm này. Tôi không thể tìm ra nếu có điều gì đó sai trong mã của chúng tôi hoặc trên môi trường Azure? Không có ajax trong các hình thức này.

Chúng tôi đã thêm phần <machineKey> vào web.config của chúng tôi. Không có bộ nhớ đệm. Đôi khi nó xảy ra trên các thiết bị mới từ lần đầu tiên.

+0

Bạn đã bao giờ tìm thấy câu trả lời cho điều này chưa? –

+0

Không, chúng tôi đã phải loại bỏ kiểm tra chống ung thư (nó đã được sử dụng cho các hình thức tích hợp đơn giản. Không có gì quan trọng về nó). Thiết lập Azure của chúng tôi có hai đĩa CD logic, do đó, tôi đoán nó có liên quan đến các đĩa CD khác nhau xử lý yêu cầu và phản hồi. Đó chỉ là phỏng đoán của tôi. – TamerM

+0

Tôi rất buồn khi nghe điều đó, mặc dù tôi không nghĩ rằng đây là vấn đề, trừ khi bạn có miền được xác định trong hành động biểu mẫu (sau đó chuyển hướng người dùng sang một đĩa CD khác cho POST, nhưng tôi nghi ngờ rằng sẽ là trường hợp vì nếu bạn đã sử dụng UrlHelper, điều đó không chuyển hướng người dùng giữa các tên miền). –

Trả lời

1

Tôi tin rằng sự cố của bạn xuất phát từ việc có nhiều biểu mẫu với các mã thông báo chống giả mạo khác nhau trên một trang. Khi trang được yêu cầu, bạn nhận được hai mã thông báo khác nhau trong các biểu mẫu trường ẩn nhưng chỉ có một mã thông báo trong cookie. Biểu mẫu POST chứa các mã thông báo không khớp gây ra lỗi.

Hãy thử cách AFT sẽ hoạt động cho bạn nếu trang chỉ chứa một biểu mẫu. Nếu nó hoạt động OK thì giả định của tôi là chính xác.

This answer chứa giải pháp khả thi cho trang có nhiều biểu mẫu tuy nhiên nó có một số nhược điểm bảo mật như được giải thích here.

Tôi không chắc tại sao mọi thứ hoạt động OK trên máy chủ cục bộ của bạn. Tôi đã tạo ứng dụng đơn giản và đã thử biểu mẫu POST với mã thông báo cookie chính xác nhưng mã thông báo Biểu mẫu cũ từ phiên trước đó. Tôi ngạc nhiên khi POST thành công. Có thể asp.net có một số xử lý đặc biệt cho các yêu cầu địa phương trong trường hợp này. Tôi chưa tìm thấy bất kỳ thông tin nào về điều này.

Nếu câu trả lời của tôi vẫn không giúp bạn, bạn có thể vui lòng cung cấp số liệu sau đây để phân tích thêm:

  1. yêu cầu trang gốc với tiêu đề HTTP trở lại và tạo thẻ chống giả mạo.
  2. Yêu cầu POST biểu mẫu với tiêu đề HTTP đã gửi.
+0

Dựa trên bài đăng của OP, vấn đề không khớp với mã thông báo (btw nếu bạn có nhiều mã thông báo), và dường như không phải là vấn đề luôn luôn hiện diện. Ngoài ra, ASP.NET giải mã mã thông báo chống giả mạo trước khi so sánh. Nó không quan trọng nếu bạn có 2 thẻ khác nhau trong một hình thức nếu cả hai đều chứa dữ liệu tương ứng với cookie. Ngoài ra, tôi thấy trong hệ thống của riêng tôi rằng nhiều biểu mẫu và mã thông báo biểu mẫu không phải là vấn đề, vấn đề là không có cookie nào được gửi bởi trình duyệt. –

+0

Đúng, mã thông báo không chỉ được so sánh như bộ đệm nhị phân, mà còn được giải mã và so sánh với mã thông báo bảo mật được giữ bên trong. Bài viết hay về các thẻ nội dung chống giả mạo: https://www.codeproject.com/Articles/793384/ASP-NET-Anti-Forgery-Tokens-internals. OP đã đề cập rằng đôi khi anh ta nhận được 'mã thông báo không phù hợp với lỗi' nên giả định của tôi vẫn có thể là một vấn đề. Nếu không, sau đó thông tin tôi đã yêu cầu ở dưới cùng của câu trả lời của tôi nên làm rõ ít nhất cho dù đó là một vấn đề của khách hàng địa phương hoặc máy chủ từ xa. – CodeFuller

0

Sau khi chi tiêu một số lượng đáng kể thời gian với cuộc điều tra, sử dụng một sự kết hợp của Sentry và Azure bản ghi máy chủ web, tôi đã tìm thấy 2 nguyên nhân chính của các lỗi được đề cập:

1) Trên điện thoại di động, khi trình duyệt đang chạy ẩn, hệ điều hành có thể đột ngột dừng lại để giải phóng tài nguyên. Khi điều này xảy ra, thông thường, trang được lưu trữ trên ổ đĩa của điện thoại và được tải lại từ đó khi trình duyệt được mở lại.

Vấn đề, tuy nhiên, vào thời điểm này, Mã thông báo chống giả mạo, là cookie phiên, đã hết hạn vì đây thực chất là phiên mới. Vì vậy, trang tải mà không có Cookie chống Giả mạo, sử dụng HTML từ phiên trước đó. Điều này gây ra ngoại lệ The required anti-forgery cookie is not present.

2) Trong khi dường như có liên quan, ngoại lệ tokens do not match thường chỉ liên quan đến tiếp tuyến. Nguyên nhân có vẻ là hành vi của người dùng khi mở nhiều tab cùng một lúc.

Cookie chống giả mạo chỉ được chỉ định khi người dùng đến trang có biểu mẫu trên đó. Điều này có nghĩa là họ có thể truy cập trang chủ của bạn và không có cookie chống giả mạo. Sau đó, họ có thể mở nhiều tab bằng cách nhấp chuột giữa. Nhiều tab là nhiều yêu cầu song song, mỗi yêu cầu không có cookie chống giả mạo.

Vì những yêu cầu này không có cookie chống giả mạo, cho mỗi người trong số họ, ASP.NET tạo ra một mã thông báo giả ngẫu nhiên riêng biệt cho cookie của họ và sử dụng nó trong biểu mẫu; tuy nhiên, chỉ kết quả của tiêu đề cuối cùng nhận được sẽ được giữ lại. Điều này có nghĩa là tất cả các trang khác sẽ có mã thông báo không hợp lệ trên trang, vì cookie chống giả mạo của họ bị ghi đè.

Đối với một giải pháp, tôi đã tạo ra một bộ lọc toàn cầu phải đảm bảo rằng

  1. Cookie Chống giả mạo được gán vào bất kỳ trang nào, ngay cả khi trang không có hình thức, và
  2. Các Chống Cookie -Forgery không phải là phiên ràng buộc. Tuổi thọ của nó phải được điều chỉnh để khớp với mã thông báo đăng nhập của người dùng, nhưng nó phải tồn tại giữa các phiên trong trường hợp thiết bị di động tải lại trang mà không có phiên.

Mã bên dưới là FilterAttribute phải được thêm vào bên trong FilterConfig.cs làm bộ lọc chung. Xin lưu ý rằng, trong khi tôi không tin rằng điều này sẽ tạo ra một lỗ hổng bảo mật, tôi không có nghĩa là một chuyên gia bảo mật, vì vậy bất kỳ đầu vào được chào đón.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class AntiForgeryFilter : FilterAttribute, IActionFilter 
{ 
    public void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var cookie = filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName); 
     var addCookie = true; 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      cookie = filterContext.HttpContext.Response.Cookies.Get(AntiForgeryConfig.CookieName); 
      addCookie = false; 
     } 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      AntiForgery.GetTokens(null, out string cookieToken, out string _); 
      cookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) 
      { 
       HttpOnly = true, 
       Secure = AntiForgeryConfig.RequireSsl 
      }; 
     } 
     cookie.Expires = DateTime.UtcNow.AddYears(1); 
     if(addCookie) filterContext.HttpContext.Response.Cookies.Add(cookie); 
    } 

    public void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
    } 
} 
Các vấn đề liên quan