Ghi đè thuộc tính ủy quyền trong ASP.NET MVC


83

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

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

Có ý kiến ​​gì không?

Câu trả lời:


100

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 AllowAnonymous được tích hợp sẵn .

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

Bạn có thể tạo thuộc tính ủy quyền tùy chỉnh kế thừa từ AuthorizeAttribute tiêu chuẩn với thông số bool tùy chọn để chỉ định xem ủy quyền có 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í bộ điều khiển cơ sở của mình với thuộc tính đó:

[OptionalAuthorize]
public class ControllerBase : Controller
{
}

và đối với bất kỳ bộ điều khiển nào bạn không muốn ủy quyền, chỉ cần sử dụng ghi đè bằng 'false' - ví dụ:

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

Tôi đã nghĩ đến điều này nhưng tôi đã hy vọng 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.
Andrei Rînea

2
Tốt hơn là sử dụng [AllowAnonymous]thuộc tính.
Jaider

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

Bạn có biết tại sao điều này thực sự TỐT HƠN khi sử dụng AllowAnonymous không? Bởi vì bạn có quyền kiểm soát tốt hơn. Trong trường hợp của tôi, tôi đang tìm cách tắt các điểm cuối Ủy quyền chỉ cho một số môi trường nhất định, ví dụ như bạn không cần nó cho localhost. Điều này cung cấp một giải pháp thanh lịch hơn những gì tôi sẽ làm trong startup.cs của mình. 11 năm sau chúng ta sẽ nói chuyện ở đây.
sksallaj


15

Cá nhân tôi đảm nhận việc này là tách 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 xác thực - ở đây bạn có tất cả "công cụ cơ sở" của mình :).

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

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


6

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

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);
            }
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.