Версія заявок MVC5 атрибута Authorize


77

Я випробовую деякі новинки у VS2013 RC за допомогою MVC5 та нового проміжного програмного забезпечення для автентифікації OWIN.

Отже, я звик використовувати [Authorize]атрибут для обмеження дій за роллю, але я намагаюся використовувати авторизацію на основі претензій / діяльності, і я не можу знайти для нього еквівалентний атрибут.

Чи є очевидний, якого мені бракує, чи мені потрібно прокрутити своє? Я напевно очікував, що там буде один із коробки.

Що я конкретно шукаю, це щось на зразок того, що [Authorize("ClaimType","ClaimValue")]я припускаю.

Заздалегідь спасибі.


1
просто як пропозицію, будь ласка, поставте розділ ОБНОВЛЕННЯ як нову відповідь, так що всім зрозуміло, що це інший підхід (і не є частиною вашого запитання)
g3rv4

Я б це зробив, але тоді я хотів би прийняти власну відповідь, .. і це просто не те, що робить джентльмен :-)
EightyOne Unite

1
Я запитав саме це про мета, і ось, що вони відповіли meta.stackexchange.com/questions/216719/ ... так що, здається, є консенсус;)
g3rv4

@ Stimul8d Я повинен погодитися з Гервасіо - питання - для питань, відповіді - для відповідей. Вам не доведеться позначати це як прийняте, якщо ви цього не хочете; але це стало б зрозумілішим для інших людей.
dav_i 02.03.15

2
Я думаю, що жорстоко, що ця технологія не поставляється з сантехнікою для атрибутів, порівняно з реалізацією для ролей.
Пітсбурзький DBA,

Відповіді:


73

У підсумку я просто написав простий атрибут для обробки. Я не міг знайти щось у фреймворку прямо з коробки без купу додаткових налаштувань. Перечислені нижче.

public class ClaimsAuthorizeAttribute : AuthorizeAttribute
{
    private string claimType;
    private string claimValue;
    public ClaimsAuthorizeAttribute(string type, string value)
    {
        this.claimType = type;
        this.claimValue = value;
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var user = filterContext.HttpContext.User as ClaimsPrincipal;
        if (user != null && user.HasClaim(claimType, claimValue))
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

Звичайно, ви могли б видалити параметри типу та значення, якщо б вам було приємно якось використовувати триплет controller-action-verb для претензій.


6
Для прямої сумісності найкраще використовувати filterContext.HttpContext.user.
Ерік Філіпс,

1
У підсумку я зробив щось майже ідентичне, але це змушує менталітет рольового стилю з точки зору застосування атрибутів. Розділення питань, які підтримує @leastprivilege, виглядає набагато сильнішим.
Пітсбурзький DBA,

2
@ Stimul8d Дякую за відповідь, це чудово вийшло в моєму додатку MVC 5! Мені має сенс реалізувати ваш власний ClaimsAuthorizationAttribute, а потім іти з ClaimsAuthorizationManager (потрібно занадто багато конфігурації)
landsteven

1
Хороша відповідь, особливо тому, що навіть я зміг це зрозуміти та включити.
Василь Холл

Хороша відповідь - я повернув HTTP 403, щоб запобігти поверненню назад на сторінку входу. Що стосується ролей, ви можете використовувати їх аналогічно заявам. Замість однієї ділової ролі, такої як ADMIN, використовуйте багато ролей, таких як CanSaveData. Вам потрібна спеціальна таблиця, яка відображає псевдоролю АДМІНІСТРАТОР для всіх ролей, членом яких вона є. Претензії - це шлях, як ти вбудований
pixelda

30
  1. Ви не будете перевіряти конкретно претензії, а скоріше, пара дій / ресурсів. Виділіть фактичні перевірки заявок / даних у менеджер авторизації. Поділ проблем.
  2. MVC і ClaimsPrincipalPermission не дуже добре поєднуються. Він створює SecurityException і не є дружнім для тестування.

Моя версія тут: http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/


2
Ваша версія, здається, не в останній збірці MVC 5? Якщо так, який пакет Nuget його містить?
Brian Mains

2
nuget.org/packages/Thinktecture.IdentityModel.SystemWeb - і він перейменований на ResourceActionAuthorizeAttribute
najmanний привілей

4
@leastprivilege Думаю, мало б сенс оновити допис у своєму блозі інформацією про перейменований атрибут та доступні пакунки nuget для MVC та Web API 2.x? Я не знаю, як я повинен був знати про перейменування, якби не цей розділ коментарів;)
Лассе Крістіансен,

4
Я не знаю, чи ця відповідь все ще актуальна, але я все ще не уявляю, що таке ресурс або яке відношення він має до дій контролера та заявлених мною претензій. Розглядаючи це як хтось, хто не є експертом Owin, чи не могли б ви трохи розширити відповідь, будь ласка?
Крейг Бретт,

1
Використання атрибута все ще є проблемою, оскільки логіка знаходиться всередині коду атрибута, зберігаючи властивість атрибуту досить близько для розробника, тому він не забуде його.
Softlion

9

Я виявив, що ви все ще можете використовувати атрибут Authorization з ролями та користувачами, із заявами.
Щоб це працювало, ваша ClaimsIdentity повинна включати 2 конкретні типи претензій:

    ClaimTypes.Name

і

    ClaimTypes.Role

Потім у своєму класі, похідному від OAuthAuthorizationServerProvider, у використовуваних вами методах GrantXX, коли ви створюєте ClaimsIdentity, додайте ці 2 твердження.

Приклад:

    var oAuthIdentity = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.Name, context.ClientId),
        new Claim(ClaimTypes.Role, "Admin"),
    }, OAuthDefaults.AuthenticationType);

Тоді на будь-яку дію, яку ви можете використовувати [Authorize(Roles ="Admin")]для обмеження доступу.


Це робить фокус! Що мене зачепило, це не регенерація маркера після внесення змін - до! Щоб зрозуміти, з наведеним вище кодом [Authorize (Roles = "Admin")] - це те, що потрібно для обмеження доступу до методу.
Kinetic

4

В ASP.NET Core 3 ви можете налаштувати такі політики безпеки:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

потім використовуйте AuthorizeAttribute, щоб вимагати, щоб користувач відповідав вимогам певної політики (іншими словами, задовольнити претензію, що підтримує цю політику).

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

Джерело .


3
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Delete", Resource="Customer")]
public ActionResult Delete(int id)
{
    _customer.Delete(id);
    return RedirectToAction("CustomerList");
}

Клас ClaimsPrincipalPermissionAttribute


2
Здається, це правильно, але це багато роботи з ногами та додаткові посилання на те, що має бути спеченим. Я прийняв відповідь, але перевірте мою редакцію.
EightyOne Unite

1
Чи не створює це виняток замість того, щоб повернути відповідну відповідь HTTP?
Ронні Овербі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.