15

Tôi có ứng dụng với nhiều hành động ajax (được triển khai bằng cách sử dụng JQuery.ajax), trả về JSON ot html. Một số người trong số họ chỉ có thể truy cập được đối với người dùng được ủy quyền và tôi đã trang trí chúng với thuộc tính [Authorize]. Đối với hành động không phải ajax, nếu người dùng không được ủy quyền - hệ thống sẽ chuyển hướng anh ta đến trang đăng nhập (được định cấu hình trong web.config).Kết quả trái phép trong yêu cầu ajax

Nhưng điều này không áp dụng cho hành động ajax, bởi vì nếu người dùng được ủy quyền - anh ta tải trang, sau khi cookie đó hết hạn và anh ta không được ủy quyền, thay vì khối html, thay thế cũ, anh ấy sẽ nhận được trang đăng nhập của tôi khối.

Tôi biết rằng tôi có thể giải quyết vấn đề này theo cách thủ công, ví dụ: xóa thuộc tính [Ủy quyền] và trả về json/html trống đặc biệt nếu người dùng không được phép. Nhưng tôi không thích giải pháp này, bởi vì tôi cần phải viết lại tất cả các hành động của tôi và chức năng ajax. Tôi muốn giải pháp toàn cầu, cho phép tôi không viết lại các hành động của mình (có thể là thuộc tính ủy quyền tùy chỉnh, hoặc một số xử lý tùy chỉnh kết quả trái phép http).

Tôi muốn trả lại mã trạng thái, nếu yêu cầu là ajax và chuyển hướng đến trang đăng nhập, nếu yêu cầu không phải là ajax.

+0

"Tôi muốn trở lại mã trạng thái, nếu yêu cầu là ajax, và chuyển hướng đến trang đăng nhập, nếu yêu cầu không được Ajax." - Có vẻ như bạn đã vạch ra giải pháp cho vấn đề này, phải không? –

+0

Bạn đã cố gắng làm gì vào thời điểm này? Sẽ có một số viết lại liên quan bất kể bạn đi theo con đường nào. –

+0

Thỉnh thoảng tôi là một thằng ngốc. Hãy thử sử dụng Request.isAjaxRequest(); – Ohgodwhy

Trả lời

28

Thêm trình xử lý Application_EndRequest vào mã của bạn trong global.asax.cs sửa đổi bất kỳ lỗi 302 nào (chuyển hướng đến trang đăng nhập) thành lỗi 401 (trái phép) cho yêu cầu AJAX. Điều này sẽ cho phép bạn chỉ đơn giản là để lại hành động điều khiển của bạn như họ đang có và xử lý các chuyển hướng (bạn thực sự chỉ có thể có đăng nhập người dùng một lần nữa nếu họ không phải là hiện tại) thông qua khách hàng.

protected void Application_EndRequest() 
{ 
    // Any AJAX request that ends in a redirect should get mapped to an unauthorized request 
    // since it should only happen when the request is not authorized and gets automatically 
    // redirected to the login page. 
    var context = new HttpContextWrapper(Context); 
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest()) 
    { 
     context.Response.Clear(); 
     Context.Response.StatusCode = 401; 
    } 
} 

Sau đó, trong tập tin _Layout.cshtml bạn thêm một lỗi xử lý AJAX toàn cầu mà chuyển hướng đến hành động đăng nhập của bạn khi nó được một phản ứng 401.

<script type="text/javascript"> 
    $(function() { 
     $(document).ajaxError(function (e, xhr, settings) { 
      if (xhr.status == 401) { 
       location = '@Url.Action("login", "account")'; 
      } 
     }); 
    }); 
</script> 

Bạn cũng có thể muốn thử một số kỹ thuật được nêu trong blog của Phil Haack của, Prevent Forms Authentication Login Page Redirect When You Don’t Want It

+2

if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest() && context.Response.RedirectLocation.StartsWith ("/ Tài khoản/Đăng nhập")) Tôi đề nghị thêm RedirectLocation trong điều kiện, nếu không nó có thể bắt được một số chuyển hướng khác và trả về trái phép ... mà không được mong muốn .. – cnom

1

Bạn không phải viết lại tất cả các hành động của mình, chỉ cần tạo bộ lọc tùy chỉnh để thay thế bộ lọc được xây dựng Authorize.

Những người khác đã thực hiện nó trước khi

asp.net mvc [handleerror] [authorize] with JsonResult?

0

Bạn có thể kiểm tra các phương pháp khuyến nông Request.IsAjaxRequest() và có hành động cụ thể nếu đó là sự thật.

0

Có lẽ hành động đăng nhập của bạn trong AccountController của bạn (hoặc bất cứ nơi nào bạn có nó) có thể trả về một kết quả khác nhau nếu Request.IsAjaxRequest() là thật.

Điều này có nghĩa rằng nếu một cuộc gọi AJAX đến một hành động có thẩm quyền không cho phép, bạn sẽ có thể để trả lại một phản ứng thích hợp thông qua các hành động Logon ..

ví dụ

public ActionResult LogOn() 
{ 
    if (Request.IsAjaxRequest()) 
    { 
     // do appropriate response for ajax call here 
    } 

    return View(); 
} 

Sau đó, bạn không cần phải làm một chính viết lại