2009-04-14 47 views
77

Tôi có một lớp cơ sở điều khiển MVC mà trên đó tôi đã áp dụng thuộc tính Authorize vì tôi muốn gần như tất cả các bộ điều khiển (và hành động của chúng cùng) được ủy quyền.Ghi đè thuộc tính ủy quyền trong ASP.NET MVC

Tuy nhiên, tôi cần phải có bộ điều khiển và hành động của bộ điều khiển khác không được ủy quyền. Tôi muốn để có thể trang trí chúng với [Authorize(false)] hoặc một cái gì đó nhưng điều này là không có sẵn.

Bất kỳ ý tưởng nào?

Trả lời

70

Dường như ASP.NET MVC 4 'cố định' này bằng cách thêm một thuộc tính AllowAnonymous.

David Hayden wrote about this:

[Authorize] 
public class AccountController : Controller 
{ 
    [AllowAnonymous] 
    public ActionResult Login() 
    { 
     // ... 
    } 

    // ... 
} 
96

Chỉnh sửa: Vì ASP.NET MVC 4 cách tiếp cận tốt nhất chỉ đơn giản là sử dụng thuộc tính được xây dựng trong AllowAnonymous.

Câu trả lời dưới đây đề cập đến phiên bản trước của ASP.NET MVC

Bạn có thể tạo một thuộc tính cho phép tùy chỉnh kế thừa từ các AuthorizeAttribute tiêu chuẩn với một tham số bool tùy chọn để xác định xem uỷ quyền là cần thiết hay không.

public class OptionalAuthorizeAttribute : AuthorizeAttribute 
{ 
    private readonly bool _authorize; 

    public OptionalAuthorizeAttribute() 
    { 
     _authorize = true; 
    } 

    public OptionalAuthorizeAttribute(bool authorize) 
    { 
     _authorize = authorize; 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if(!_authorize) 
      return true; 

        return base.AuthorizeCore(httpContext); 
    } 
} 

Sau đó, bạn có thể trang trí điều khiển cơ sở của bạn với thuộc tính:

[OptionalAuthorize] 
public class ControllerBase : Controller 
{ 
} 

và cho bất kỳ bộ điều khiển mà bạn không muốn cho phép chỉ cần sử dụng ghi đè lên với một 'false' - ví dụ

[OptionalAuthorize(false)] 
public class TestController : ControllerBase 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 
} 
+0

Tôi đã nghĩ đến điều này, nhưng tôi đã hy vọng cho một giải pháp đơn giản hơn. Tuy nhiên, nếu "họ" không cung cấp thì giải pháp của bạn là giải pháp tốt nhất. –

+2

Tốt hơn nên sử dụng thuộc tính '[AllowAnonymous]'. – Jaider

+0

Chờ ... để bộ điều khiển chỉ ghi nhận thuộc tính của lớp cấp cao nhất của một loại cụ thể? – Triynko

15

Việc cá nhân tôi thực hiện việc này là chia bộ điều khiển. Chỉ cần tạo một bộ điều khiển khác Đối với các hành động bạn không cần xác thực.

Hoặc bạn có thể có:

  • BaseController
    không yêu cầu chứng thực - ở đây bạn có tất cả "công cụ cơ sở" của bạn :).

  • BaseAuthController : BaseController
    tất cả các hành động ở đây đều yêu cầu xác thực.

Bằng cách đó bạn có thể xác thực khi bạn muốn, chỉ bằng cách bắt nguồn từ một lớp cụ thể.

6

Nếu bạn chỉ muốn một hành động là trái phép trên một bộ điều khiển khác có thẩm quyền bạn có thể làm một cái gì đó như thế này:

public class RequiresAuthorizationAttribute : ActionFilterAttribute 
{ 
    private readonly bool _authorize; 

    public RequiresAuthorizationAttribute() 
    { 
     _authorize = true; 
    } 

    public RequiresAuthorizationAttribute(bool authorize) 
    { 
     _authorize = authorize; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var overridingAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequiresAuthorizationAttribute), false); 

     if (overridingAttributes.Length > 0 && overridingAttributes[0] as RequiresAuthorizationAttribute != null && !((RequiresAuthorizationAttribute)overridingAttributes[0])._authorize) 
      return; 

     if (_authorize) 
     { 
      //redirect if not authenticated 
      if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       //use the current url for the redirect 
       var redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; 

       //send them off to the login page 
       //var redirectUrl = string.Format("?RedirectUrl={0}", redirectOnSuccess); 
       var loginUrl = LinkBuilder.BuildUrlFromExpression<HomeController>(filterContext.RequestContext, RouteTable.Routes, 
                        x => x.Login(redirectOnSuccess)); 
       filterContext.HttpContext.Response.Redirect(loginUrl, true); 
      } 
     } 
    } 
} 
Các vấn đề liên quan