2011-08-11 27 views
14

tôi đè lớp để thực hiện tùy chỉnh AuthorizationSet trang 403 lỗi trong MVC

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAuthenticated) 
     { 
      filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403); 
     } 
     else 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
} 

bây giờ trong web.config tôi đã cấu hình trang 403 lỗi

<customErrors defaultRedirect="/Shared/Error" mode="On"> 
    <error statusCode="403" redirect="/Shared/UnAuthorize" /> 
</customErrors> 

nhưng trình duyệt vẫn cho thấy tôi mặc định trang lỗi cho 403, những gì tôi thiếu ở đây, bất kỳ ý tưởng nào

Trả lời

11

Chỉ cần một gợi ý nhỏ/note bên cạnh Max B. câu trả lời:

Khi tôi đang sử dụng lỗi tùy chỉnh tôi thực hiện một ErrorsController, và một UnAuthorize ActionResult và làm như sau:

<error statusCode="403" redirect="/Errors/UnAuthorize" /> 

Bằng cách này tôi có thể thêm thông tin thêm hoặc làm các hành động khác trong bộ điều khiển của tôi, ví dụ:

  • Giống như đăng nhập vào cơ sở dữ liệu mà ai đó đã cố truy cập khu vực đã được xác thực.
  • Lỗi đếm.
  • Có thể một lỗi hoặc biểu mẫu báo cáo mà họ có thể sử dụng để gửi thông tin quản trị.
  • ...

Bằng cách này, bạn có thể kiểm soát nhiều hơn những gì đang xảy ra.

+0

thực sự tôi đang làm như vậy, được chia sẻ là bộ điều khiển và trái phép là hành động, nhưng tôi vẫn nhận được lỗi mặc định http 403 trang, không phải trang xác định của tôi –

+1

liên kết rất hữu ích http://stackoverflow.com/questions/2504923/how -to-redirect-authorise-to-loginurl-only-khi-vai trò-không-được sử dụng –

+2

@SaboorAwan. Tôi đã thử cùng với không may mắn. Phương thức điều khiển không bao giờ được gọi. Bạn có giải quyết được vấn đề với câu trả lời này hoặc với liên kết bạn đã đăng không? – Marco

-1

Với tôi, có vẻ như HttpStatusCodeResult (403) bị sai nếu nhánh. Theo tôi các mã sẽ giống như thế này:

+1

Bạn có thể muốn kiểm tra ... nó phá vỡ yêu cầu Cấp phép khi Được xác thực. – JustinStolle

3

Hoặc bạn có thể làm giải pháp thay thế này, thay vì sử dụng:

filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403); 

bạn có thể thay đổi nó thành:

if (filterContext.HttpContext.Request.IsAuthenticated) 
     {    
      throw new UnauthorizedAccessException(); 
     } 

Và phương pháp ghi đè OnException (ExceptionContext filterContext) trong điều khiển của bạn/BaseController

protected override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.ExceptionHandled) 
     { 
      return; 
     } 

     if (filterContext.Exception.GetType() == typeof(UnauthorizedAccessException)) 
     { 
      filterContext.Result = new ViewResult 
      { 
       ViewName = "~/Views/Error/NotAuthorized.cshtml" 
      }; 
      filterContext.ExceptionHandled = true; 
      return; 
     } 

     base.OnException(filterContext); 
    } 
6

Tôi gặp vấn đề tương tự như khi bạn viết m y tùy chỉnh AuthorizeAttribute. Trang lỗi tùy chỉnh cho 403 sẽ không hiển thị khi tôi thêm thẻ "customErrors" vào web.config. Đây là cách tôi đã nhận nó giải quyết:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAuthenticated) 
     { 
      filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary(
        new 
         { 
          controller = "Error", 
          action = "Unauthorised" 
         }) 
       ); 

     } 
     else 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
} 

Assigned một con đường mà tôi muốn để hiển thị cho filterContext.Result, thay vì gán 403 HttpStatusCode.

8

Tôi biết đây là câu hỏi rất cũ, nhưng tôi đang đăng bài cho những người có cùng vấn đề. Giống như tôi, tôi đã có cùng một vấn đề và giải quyết nó. Nếu bạn muốn kích hoạt phần tử customErrors trong web.config, bạn có thể thử dưới đây.

protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
{ 
    throw new HttpException(403, "Forbidden"); 
} 
+0

Hoạt động hoàn hảo và dễ dàng hơn các giải pháp khác. – Guillaume

+2

bạn đặt cái này ở đâu? Sẽ được tốt đẹp để thêm. Nó có thể là khu vực cụ thể? – CularBytes

+0

@RageCompex Bạn có thể đặt chúng trong lớp thuộc tính tùy chỉnh của bạn. Và bạn có thể giải thích thêm về 'Khu vực cụ thể' không? – user3110409

0

Cách xử lý 401 (Không được phép), 403 (Bị cấm) và 500 (Lỗi máy chủ nội bộ) trong mvc. Đối với các cuộc gọi ajax/non-ajax và dưới hình thức xác thực aspx.

Nó có thể được thay đổi để xử lý các trường hợp ngoại lệ chưa được nhận khác nhau và phản ứng khác nhau cho dù yêu cầu là ajax hay không. Phần auth cho phép nó bỏ qua bất kỳ biểu mẫu web chuyển hướng-to-login-trang mvc thông thường nào và thay vào đó trả về 401 trái phép - thì khung công tác js phía máy khách của bạn có thể phản ứng với trạng thái http 401403 dễ dàng hơn.

// FilterConfig.cs: 
filters.Add(new ApplicationAuthorizeAttribute()); 
filters.Add(new ApplicationHandleErrorAttribute()); 

public class ApplicationAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     // Note: To reach here, a Web.config path-specific rule 'allow users="?"' is needed (otherwise it redirects to login) 

     var httpContext = filterContext.HttpContext; 
     var request = httpContext.Request; 
     var response = httpContext.Response; 

     if (request.IsAjaxRequest()) 
     { 
      response.SuppressFormsAuthenticationRedirect = true; 
      response.TrySkipIisCustomErrors = true; 
     } 

     filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

public class ApplicationHandleErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     var exception = context.Exception is AggregateException 
      ? ((AggregateException)context.Exception).InnerExceptions.First() 
      : context.Exception; 
     var request = context.HttpContext.Request; 
     var response = context.HttpContext.Response; 
     var isAjax = request.IsAjaxRequest(); 

     if (exception is MyCustomPermissionDeniedException) 
     { 
      filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); 
      response.TrySkipIisCustomErrors = isAjax; 
      filterContext.ExceptionHandled = true; 
      return; 
     } 

#if DEBUG 
     if (!isAjax) 
     { 
      // Show default aspx yellow error page for developers 
      return; 
     } 
#endif 

     var requestUri = request.Url == null ? "" : request.Url.AbsoluteUri; 
     MyCustomerLogger.Log(exception, requestUri); 

     response.Clear(); 
     response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; 

#if DEBUG 
     var errorMessage = exception.Message; 
#else 
     var errorMessage = "An error occurred, please try again or contact the administrator."; 
#endif 

     response.Write(isAjax 
      ? JsonConvert.SerializeObject(new {Message = errorMessage}) 
      : errorMessage); 
     response.End(); 
     response.TrySkipIisCustomErrors = true; 
     context.ExceptionHandled = true; 
    } 
} 

Web.config:

<system.webServer> 

<authentication mode="Forms"> 
    <forms name=".MYAUTHCOOKIE" protection="All" loginUrl="/Account/Login" timeout="18000" slidingExpiration="true" enableCrossAppRedirects="false" /> 
</authentication> 

<authorization> 
    <deny users="?" /> 
</authorization> 

</system.webServer> 

<!-- ajax api security done via ApplicationAuthorizeAttribute --> 
<location path="api"> 
    <system.web> 
    <authorization> 
     <allow users="?"/> 
    </authorization> 
    </system.web> 
</location> 

tuyến đường bổ sung cho các yêu cầu api dịch vụ web: (đặt trên tuyến đường thường xuyên MVC)

// This route has special ajax authentication handling (no redirect to login page) 
routes.MapRoute(
    name: "DefaultApi", 
    url: "api/{controller}/{action}/{id}", 
    defaults: new { id = UrlParameter.Optional } 
); 

mẫu client side code cho jquery để xử lý các lỗi :

$.ajaxSetup({ 
    complete: function onRequestCompleted(xhr, textStatus) { 
     if (xhr.readyState == 4 && xhr.status == 401) { 
      // Not needed with smart status: && xhr.responseText.substring(0, 150).indexOf("<title>Log in") != -1 
      //location.href = "/Account/Login"; 
      alert("Your session has timed out."); 
     } 
    } 
}); 

Ngoài ra, bạn có thể làm cho tất cả các auth đi qua ApplicationHandleErrorAttribute, và thoát khỏi web.config deny users = "?". Nhưng tôi có một trang aspx di sản mà không nhấn lọc mvc vì vậy tôi muốn từ chối người dùng = "?".

+0

Bạn thực sự có thể F12 (resharper decompile? Ms symbol server?) Thành: ControllerActionInvoker, HandleErrorAttribute, AuthorizeAttribute. Đây là cách đọc rất sáng suốt. ControllerActionInvoker sử dụng từng loại bộ lọc 4 khác nhau. (auth, hành động, kết quả, ngoại lệ) ví dụ: Tới bộ điều khiển của bạn, nhấn F12 trên lớp cơ sở "Controller", F12 trên "IAuthorizationFilter", Shift-F12 trên "OnAuthorization". –

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