Atribut Otorisasi Kustom ASP.NET MVC 4 dengan Kode Izin (tanpa peran)

121

Saya perlu mengontrol akses ke tampilan berdasarkan tingkat hak istimewa pengguna (tidak ada peran, hanya tingkat hak istimewa untuk tingkat operasi CRUD yang ditetapkan ke pengguna) di aplikasi MVC 4 saya.

Sebagai contoh; di bawah AuthorizeUser akan menjadi atribut khusus saya dan saya perlu menggunakannya seperti ini:

[AuthorizeUser(AccessLevels="Read Invoice, Update Invoice")]
public ActionResult UpdateInvoice(int invoiceId)
{
   // some code...
   return View();
}


[AuthorizeUser(AccessLevels="Create Invoice")]
public ActionResult CreateNewInvoice()
{
  // some code...
  return View();
}


[AuthorizeUser(AccessLevels="Delete Invoice")]
public ActionResult DeleteInvoice(int invoiceId)
{
  // some code...
  return View();
}

Apakah mungkin melakukannya dengan cara ini?

chatura
sumber

Jawaban:

243

Saya dapat melakukannya dengan atribut khusus sebagai berikut.

[AuthorizeUser(AccessLevel = "Create")]
public ActionResult CreateNewInvoice()
{
    //...
    return View();
}

Kelas Atribut Khusus sebagai berikut.

public class AuthorizeUserAttribute : AuthorizeAttribute
{
    // Custom property
    public string AccessLevel { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (!isAuthorized)
        {                
            return false;
        }

        string privilegeLevels = string.Join("", GetUserRights(httpContext.User.Identity.Name.ToString())); // Call another method to get rights of the user from DB

        return privilegeLevels.Contains(this.AccessLevel);           
    }
}

Anda dapat mengalihkan pengguna yang tidak sah di kustom Anda AuthorisationAttributedengan mengganti HandleUnauthorizedRequestmetode:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(
                    new
                        { 
                            controller = "Error", 
                            action = "Unauthorised" 
                        })
                );
}
chatura
sumber
Saya sudah mencoba contoh HandleUnauthorizedRequest tetapi ketika saya menentukan RouteValueDictionary, itu hanya mengarahkan saya ke rute yang tidak ada. Ini menambahkan rute yang ingin saya arahkan pengguna ke rute yang ingin diakses pengguna ... si Saya mendapatkan sesuatu seperti: localhost: 9999 / admin / Home ketika saya menginginkan localhost: 9999 / Home
Marin
1
@Marin Cobalah untuk menambahkan area = string. Kosong di RouteValueDictionary
Alex
30
Saya melakukan upvoting tetapi kemudian saya melihat "if (kondisi) {return true;} else {return false;}" di akhir ....
GabrielBB
1
@Emil Saya hanya akan mengembalikan boolean yang diberikan metode String.Contains kepada saya. Tapi ini tidak relevan, saya tidak downvote, saya hanya tidak upvote hehe.
GabrielBB
2
.Name.ToString()redundan, karena Nameproperti sudah berupa string
FindOutIslamNow
13

Berikut adalah modifikasi untuk prev. menjawab. Perbedaan utamanya adalah ketika pengguna tidak diautentikasi, ia menggunakan metode "HandleUnauthorizedRequest" asli untuk mengalihkan ke halaman login:

   protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {

        if (filterContext.HttpContext.User.Identity.IsAuthenticated) {

            filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary(
                            new
                            {
                                controller = "Account",
                                action = "Unauthorised"
                            })
                        );
        }
        else
        {
             base.HandleUnauthorizedRequest(filterContext);
        }
    }
Leonid Minkov
sumber
3

Mungkin ini berguna bagi siapa saja di masa mendatang, saya telah menerapkan Atribut Otorisasi khusus seperti ini:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class ClaimAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly string _claim;

    public ClaimAuthorizeAttribute(string Claim)
    {
        _claim = Claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;
        if(user.Identity.IsAuthenticated && user.HasClaim(ClaimTypes.Name, _claim))
        {
            return;
        }

        context.Result = new ForbidResult();
    }
}
RaphaelH
sumber
0

Jika Anda menggunakan WEB API dengan Klaim, Anda dapat menggunakan ini:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AutorizeCompanyAttribute:  AuthorizationFilterAttribute
{
    public string Company { get; set; }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var claims = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity);
        var claim = claims.Claims.Where(x => x.Type == "Company").FirstOrDefault();

        string privilegeLevels = string.Join("", claim.Value);        

        if (privilegeLevels.Contains(this.Company)==false)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Usuario de Empresa No Autorizado");
        }
    }
}
[HttpGet]
[AutorizeCompany(Company = "MyCompany")]
[Authorize(Roles ="SuperAdmin")]
public IEnumerable MyAction()
{....
}
Maurico Bello
sumber