2012-09-09 38 views
10

Tôi đã gặp phải sự cố nghiêm trọng với @Html.AntiForgeryToken(). Tôi có một bộ điều khiển đăng ký có chế độ xem tạo/đăng ký thành viên mới. Vì lý do đó tôi đã sử dụng @Html.AntiForgeryToken() mà không sử dụng bất kỳ SALT nào trong biểu mẫu gửi chính của mình. Bây giờ tôi muốn xác thực tên người dùng nếu nó đã tồn tại trên cơ sở dữ liệu trên sự kiện mờ của hộp văn bản tên người dùng của tôi. Để xác thực điều này, tôi đã viết một bộ điều khiển mới có tên 'Xác thực' và đã viết một phương thức có xác nhận hợp lệ SALT:Có thể/quyền sử dụng nhiều @ Html.AntiForgeryToken() ở 2 dạng khác nhau trong một trang không?

[HttpPost] 
    [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
    public ActionResult username(string log) { 
     try { 
      if (log == null || log.Length < 3) 
       return Json(log, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(log); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(log, userPattern)) 
        return Json(log, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(log, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(log, JsonRequestBehavior.AllowGet); 

    } 

Phương pháp này hoạt động tốt. Tôi đã kiểm tra bằng chú thích HTTP Get mà không cần [ValidateAntiForgeryToken] và nó cho tôi kết quả mong đợi.

Tôi đã googled và kiểm tra nhiều giải pháp đã cho mà không có giải pháp nào trong số này hoạt động. Đối với bộ điều khiển xác thực của tôi, tôi đã sử dụng một biểu mẫu khác trong cùng một trang và đã sử dụng một SALT trong mã thông báo Chống giả mạo.

Ví dụ: Đầu tiên chống giả mạo thẻ đối với hình thức nộp chính:

@using (Html.BeginForm ("Tạo", "Đăng ký")) { @ Html.AntiForgeryToken() @ Html.ValidationSummary (true) ...}

Second chống giả mạo mã thông báo:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> 
    @Html.AntiForgeryToken(SALT) 
</form> 

và trong javascript Tôi sử dụng này

<script type="text/javascript" defer="defer"> 
    $(function() { 
     AddAntiForgeryToken = function (data) { 
      data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val(); 
      return data; 
     }; 

     if ($("#LogName").length > 0) { 

      $("#LogName").blur(function() { 
       var user = $("#LogName").val(); 
       var logValidate = "/Validation/username/"; 
       //var URL = logValidate + user; 
       //var token = $('#validation input[name=__RequestVerificationToken]').val(); 
       data = AddAntiForgeryToken({ log: user }); 

       $.ajax({ 
        type: "POST", 
        dataType: "JSON", 
        url: logValidate, 
        data: data, 
        success: function (response) { 
         alert(response); 
        } 
       }); 

      }); 

     } 
    }); 
</script> 

Trong firebug của tôi, tôi nhận điều này:

log=admin&__RequestVerificationToken=NO8Kds6B2e8bexBjesKlwkSexamsruZc4HeTnFOlYL4Iu6ia%2FyH7qBJcgHusekA50D7TVvYj%2FqB4eZp4VDFlfA6GN5gRz7PB%2ByZ0AxtxW4nT0E%2FvmYwn7Fvo4GzS2ZAhsGLyQC098dfIJaWCSiPcc%2FfD00FqKxjvnqmxhXvnEx2Ye83LbfqA%2F4XTBX8getBeodwUQNkcNi6ZtAJQZ79ySg%3D%3D 

như trôi qua nhưng trong phần Cookie tôi nhận được một cookie khác nhau hơn thông qua một: Cookie Thực tế:

ws5Dt2if6Hsah rW2nDly P3cW1smIdp1Vau 0TXOK1w0ctr0BCso/nbYu w9blq/QcrXxQLDLAlKBC3Tyhp5ECtK MxF4hhPpzoeByjROUG0NDJfCAlqVVwV5W6lw9ZFp/VBcQmwBCzBM/36UTBWmWn6pMM2bqnyoqXOK4aUZ4= 

Tôi nghĩ điều này là do tôi đã sử dụng 2 mã thông báo chống giả mạo trong một trang. Nhưng trong tâm trí của tôi, tôi nên sử dụng 2 bởi vì đầu tiên là tạo ra cho trình để xảy ra và tiếp theo là cần phải xác minh xác nhận. Tuy nhiên, đây là phỏng đoán của tôi và tôi nghĩ rằng tôi sai và vì lý do này tôi cần sự giúp đỡ từ các bạn.

Có ai vui lòng giải thích sự thật rằng tôi có nên sử dụng hai giả mạo hay không?

Cảm ơn tất cả trước ....

Trả lời

8

Cuối cùng 8 giờ đấu tranh mang lại cho tôi giải pháp.

Điều đầu tiên trước tiên, không có hại gì khi sử dụng 2 mã thông báo chống giả mạo trong trang. Và thứ hai không cần phải khớp các cookie với mã thông báo cung cấp. Việc cung cấp mã thông báo sẽ luôn khác nhau và sẽ được xác minh trong máy chủ.

Chống giả mạo thẻ không hoạt động nếu chúng tôi sử dụng [HttpGet] động từ hành động .. Bởi vì trong quá trình xác nhận chống giả mạo token được xác nhận bằng cách lấy giá trị Request.Form['__RequestVerificationToken'] từ yêu cầu.ref: Steven Sanderson's blog: prevent cross...

Giải pháp:

Sửa My điều khiển:

[HttpPost] 

     [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
//change the map route values to accept this parameters. 
     public ActionResult username(string id, string __RequestVerificationToken) { 
     string returnParam = __RequestVerificationToken; 

     try { 
      if (id == null || id.Length < 3) 
       return Json(returnParam, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(id); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(id, userPattern)) 
        return Json(returnParam, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(returnParam, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(returnParam, JsonRequestBehavior.AllowGet); 
    } 

Mẫu đầu tiên của tôi trong cùng một trang:

@using (Html.BeginForm("Create", "Register")) { 

    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 

    @Html.ValidationSummary(true) 
    .... 
} 

Mẫu thứ hai của tôi trong cùng một trang:

**<form id="validation"> 
    <!-- there is harm in using 2 anti-forgery tokens in one page--> 
    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 
    <input type="hidden" name="id" id="id" value="" /> 
</form>** 

jQuery của tôi để giải quyết vấn đề này:

$("#LogName").blur(function() { 
      var user = $("#LogName").val(); 
      var logValidate = "/Validation/username/"; 
      $("#validation #id").val(user); 
      **var form = $("#validation").serialize(); // a form is very important to verify anti-forgery token and data must be send in a form.** 

      var token = $('input[name=__RequestVerificationToken]').val(); 

      $.ajax({ 
       **type: "POST", //method must be POST to validate anti-forgery token or else it won't work.** 
       dataType: "JSON", 
       url: logValidate, 
       data: form, 
       success: function (response) { 
        alert(response); 
       } 
      }); 
     }); 
Các vấn đề liên quan