Key claim что это
Перейти к содержимому

Key claim что это

  • автор:

Вы отправили слишком много запросов, поэтому ваш компьютер был заблокирован.

Для того, чтобы предотвратить автоматическое считывание информации с нашего сервиса, на Linguee допустимо лишь ограниченное количество запросов на каждого пользователя.
Пользователям, браузер которых поддерживает Javascript, доступно большее количество запросов, в отличие от пользователей, чей браузер не поддерживает Javascript. Попробуйте активировать Javascript в настройках вашего браузера, подождать несколько часов и снова воспользоваться нашим сервером.
Если же ваш компьютер является частью сети компьютеров, в которой большое количество пользователей одновременно пользуется Linguee,сообщитеоб этом нам.

Security Token Handler. Validate Token(SecurityToken) Метод

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

При переопределении в производном классе проверяет указанный токен безопасности. Токен должен иметь тип, обрабатываемый производным классом.

public: virtual System::Collections::ObjectModel::ReadOnlyCollection ^ ValidateToken(System::IdentityModel::Tokens::SecurityToken ^ token);
public virtual System.Collections.ObjectModel.ReadOnlyCollection ValidateToken (System.IdentityModel.Tokens.SecurityToken token);
abstract member ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection override this.ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection
Public Overridable Function ValidateToken (token As SecurityToken) As ReadOnlyCollection(Of ClaimsIdentity)
Параметры

Токен для проверки.

Возвращаемое значение

Идентификаторы, содержащееся в токене.

Примеры

В следующем коде показано переопределение ValidateToken метода для обработчика маркеров безопасности, который обрабатывает простые веб-маркеры (SWT). Код взят из CustomToken примера. Сведения об этом и других примерах, доступных для WIF, а также о том, где их можно скачать, см. в разделе WiF Code Sample Index.

/// /// This method validates the Simple Web Token. /// /// A simple web token. /// A Claims Collection which contains all the claims from the token. public override ReadOnlyCollection ValidateToken(SecurityToken token) < if ( token == null ) < throw new ArgumentNullException( "token" ); >SimpleWebToken simpleWebToken = token as SimpleWebToken; if ( simpleWebToken == null ) < throw new ArgumentException("The token provided must be of type SimpleWebToken."); >if ( DateTime.Compare( simpleWebToken.ValidTo.Add( Configuration.MaxClockSkew ), DateTime.UtcNow ) ValidateSignature( simpleWebToken ); ValidateAudience( simpleWebToken.Audience ); ClaimsIdentity claimsIdentity = CreateClaims( simpleWebToken ); if (this.Configuration.SaveBootstrapContext) < claimsIdentity.BootstrapContext = new BootstrapContext(simpleWebToken.SerializedToken); >List claimCollection = new List(new ClaimsIdentity[] < claimsIdentity >); return claimCollection.AsReadOnly(); > 

В следующем коде показан CreateClaims метод, который вызывается из переопределения ValidateToken метода в предыдущем примере. Этот метод возвращает ClaimsIdentity объект, созданный из утверждений в маркере. Код взят из CustomToken примера. Сведения об этом и других примерах, доступных для WIF, а также о том, где их можно скачать, см. в разделе WiF Code Sample Index.

/// Creates 's from the incoming token. /// /// The incoming . /// A created from the token. protected virtual ClaimsIdentity CreateClaims( SimpleWebToken simpleWebToken ) < if ( simpleWebToken == null ) < throw new ArgumentNullException( "simpleWebToken" ); >NameValueCollection tokenProperties = simpleWebToken.GetAllProperties(); if ( tokenProperties == null ) < throw new SecurityTokenValidationException( "No claims can be created from this Simple Web Token." ); >if ( Configuration.IssuerNameRegistry == null ) < throw new InvalidOperationException( "The Configuration.IssuerNameRegistry property of this SecurityTokenHandler is set to null. Tokens cannot be validated in this state." ); >string normalizedIssuer = Configuration.IssuerNameRegistry.GetIssuerName( simpleWebToken ); ClaimsIdentity identity = new ClaimsIdentity(AuthenticationTypes.Federation); foreach ( string key in tokenProperties.Keys ) < if ( ! IsReservedKeyName(key) && !string.IsNullOrEmpty( tokenProperties[key] ) ) < identity.AddClaim( new Claim( key, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer ) ); if ( key == AcsNameClaimType ) < // add a default name claim from the Name identifier claim. identity.AddClaim( new Claim( DefaultNameClaimType, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer ) ); >> > return identity; > 

В следующем коде показан ValidateSignature метод, который вызывается из переопределения ValidateToken метода в простом обработчике веб-маркера. Этот метод проверяет подпись маркера с помощью настроенного IssuerTokenResolver. Код взят из CustomToken примера. Сведения об этом и других примерах, доступных для WIF, а также о том, где их можно скачать, см. в разделе WiF Code Sample Index.

/// /// Validates the signature on the incoming token. /// /// The incoming . protected virtual void ValidateSignature( SimpleWebToken simpleWebToken ) < if ( simpleWebToken == null ) < throw new ArgumentNullException( "simpleWebToken" ); >if ( String.IsNullOrEmpty( simpleWebToken.SerializedToken ) || String.IsNullOrEmpty( simpleWebToken.Signature ) ) < throw new SecurityTokenValidationException( "The token does not have a signature to verify" ); >string serializedToken = simpleWebToken.SerializedToken; string unsignedToken = null; // Find the last parameter. The signature must be last per SWT specification. int lastSeparator = serializedToken.LastIndexOf( ParameterSeparator ); // Check whether the last parameter is an hmac. if ( lastSeparator > 0 ) < string lastParamStart = ParameterSeparator + SimpleWebTokenConstants.Signature + "="; string lastParam = serializedToken.Substring( lastSeparator ); // Strip the trailing hmac to obtain the original unsigned string for later hmac verification. if ( lastParam.StartsWith( lastParamStart, StringComparison.Ordinal ) ) < unsignedToken = serializedToken.Substring( 0, lastSeparator ); >> SimpleWebTokenKeyIdentifierClause clause = new SimpleWebTokenKeyIdentifierClause(simpleWebToken.Audience); InMemorySymmetricSecurityKey securityKey = null; try < securityKey = (InMemorySymmetricSecurityKey)this.Configuration.IssuerTokenResolver.ResolveSecurityKey(clause); >catch (InvalidOperationException) < throw new SecurityTokenValidationException( "A Symmetric key was not found for the given key identifier clause."); >string generatedSignature = GenerateSignature( unsignedToken, securityKey.GetSymmetricKey() ); if ( string.CompareOrdinal( generatedSignature, simpleWebToken.Signature ) != 0 ) < throw new SecurityTokenValidationException( "The signature on the incoming token is invalid.") ; >> 
/// /// Generates an HMACSHA256 signature for a given string and key. /// /// The token to be signed. /// The key used to generate the signature. /// The generated signature. protected static string GenerateSignature(string unsignedToken, byte[] signingKey) < using (HMACSHA256 hmac = new HMACSHA256(signingKey)) < byte[] signatureBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken)); string signature = HttpUtility.UrlEncode(Convert.ToBase64String(signatureBytes)); return signature; >> 

В следующем коде показан ValidateAudience метод, который вызывается из переопределения ValidateToken метода в простом обработчике веб-маркера. Этот метод проверяет аудиторию, содержащуюся в маркере, по URI аудитории, указанной в конфигурации. Код взят из CustomToken примера. Сведения об этом и других примерах, доступных для WIF, а также о том, где их можно скачать, см. в разделе WiF Code Sample Index.

/// /// Validates the audience of the incoming token with those specified in configuration. /// /// The audience of the incoming token. protected virtual void ValidateAudience( string tokenAudience ) < if ( Configuration.AudienceRestriction.AudienceMode != AudienceUriMode.Never ) < if ( String.IsNullOrEmpty( tokenAudience ) ) < throw new SecurityTokenValidationException("The incoming token does not have a valid audience Uri and the Audience Restriction is not set to 'None'."); >if ( Configuration.AudienceRestriction.AllowedAudienceUris.Count == 0 ) < throw new InvalidOperationException( " Audience Restriction is not set to 'None' but no valid audience URI's are configured." ); >IList allowedAudienceUris = Configuration.AudienceRestriction.AllowedAudienceUris; Uri audienceUri = null; Uri.TryCreate(tokenAudience, UriKind.RelativeOrAbsolute, out audienceUri); // Strip off any query string or fragment. Uri audienceLeftPart; if ( audienceUri.IsAbsoluteUri ) < audienceLeftPart = new Uri( audienceUri.GetLeftPart( UriPartial.Path ) ); >else < Uri baseUri = new Uri( "http://www.example.com" ); Uri resolved = new Uri( baseUri, tokenAudience ); audienceLeftPart = baseUri.MakeRelativeUri( new Uri( resolved.GetLeftPart( UriPartial.Path ) ) ); >if ( !allowedAudienceUris.Contains( audienceLeftPart ) ) < throw new AudienceUriValidationFailedException( "The Audience Uri of the incoming token is not present in the list of permitted Audience Uri's."); >> > 

Комментарии

По умолчанию этот метод создает NotImplementedException исключение.

Метод ValidateToken вызывается инфраструктурой для проверки и извлечения утверждений из десериализованного маркера безопасности. Эти утверждения возвращаются в коллекции объектов, ClaimsIdentity возвращаемых методом . В типичном случае эта коллекция будет содержать одно удостоверение.

В производных классах проверка обычно включает проверку целевой аудитории, указанной в токене, по URI аудитории, указанной в SecurityTokenHandlerConfiguration.AudienceRestriction свойстве объекта конфигурации обработчика маркеров, указанного в свойстве Configuration . Эти URI обычно задаются в файле конфигурации в элементе . Если аудитория не может быть проверена, AudienceUriValidationFailedException должно быть вызвано исключение.

При обработке маркера издатель обычно проверяется путем передачи маркера издателя в один из GetIssuerName методов IssuerNameRegistry объекта, настроенного для обработчика с помощью Configuration свойства . Реестр имен издателя обычно настраивается с помощью в файле конфигурации. Возвращает GetIssuerName имя издателя. Это имя следует использовать для задания Claim.Issuer свойства в утверждениях, содержащихся в маркере. Если реестр имен издателя не содержит запись для токена издателя, GetIssuerName возвращает . null В этом случае SecurityTokenException обычно создается в производных классах, но это поведение определяется конструктором класса .

Авторизация в ASP.NET Core MVC

В статье описаны паттерны и приемы авторизации в ASP.NET Core MVC. Подчеркну, что рассматривается только авторизация (проверка прав пользователя) а не аутентификация, поэтому в статье не будет использования ASP.NET Identity, протоколов аутентификации и т.п. Будет много примеров серверного кода, небольшой экскурс вглубь исходников Core MVC, и тестовый проект (ссылка в конце статьи). Приглашаю интересующихся под кат.

Claims

Принципы авторизации и аутентификации в ASP.NET Core MVC не изменились по сравнению с предыдущей версией фреймворка, отличаясь лишь в деталях. Одним из относительно новых понятий является claim-based авторизация, с нее мы и начнем наше путешествие. Что же такое claim? Это пара строк «ключ-значение», в качестве ключа может выступать «FirstName», «EmailAddress» и т.п. Таким образом, claim можно трактовать как свойство пользователя, как строку с данными, или даже как некоторое утверждение вида «у пользователя есть что-то«. Знакомая многим разработчикам одномерная role-based модель органично содержится в многомерной claim-based модели: роль (утверждение вида «у пользователя есть роль X«) представляет собой один из claim и содержится в списке преопределенных System.Security.Claims.ClaimTypes. Не возбраняется создавать и свои claim.

Следующее важное понятие — identity. Это единое утверждение, содержащее набор claim. Так, identity можно трактовать как цельный документ (паспорт, водительские права и др.), в этом случае claim — строка в паспорте (дата рождения, фамилия. ). В Core MVC используется класс System.Security.Claims.ClaimsIdentity.

Еще на уровень выше находится понятие principal, обозначающее самого пользователя. Как в реальной жизни у человека может быть на руках несколько документов одновременно, так и в Core MVC — principal может содержать несколько ассоциированных с пользователем identity. Всем известное свойство HttpContext.User в Core MVC имеет тип System.Security.Claims.ClaimsPrincipal. Естественно, через principal можно получить все claim каждого identity. Набор из более чем одного identity может использоваться для разграничения доступа к различным разделам сайта/сервиса.

На диаграмме указаны лишь некоторые свойства и методы классов из пространства имен System.Security.Claims.

Зачем это все нужно? При claim-based авторизации, мы явно указываем, что пользователю необходимо иметь нужный claim (свойство пользователя) для доступа к ресурсу. В простейшем случае, проверяется сам факт наличия определенного claim, хотя возможны и куда более сложные комбинации (задаваемые при помощи policy, requirements, permissions — мы подробно рассмотрим эти понятия ниже). Пример из реальной жизни: для управления легковым авто, у человека должны быть водительские права (identity) с открытой категорией B (claim).

Подготовительные работы

Здесь и далее на протяжении статьи, мы будем настраивать доступ для различных страниц веб-сайта. Для запуска представленного кода, достаточно создать в Visual Studio 2015 новое приложение типа «ASP.NET Core Web Application», задать шаблон Web Application и тип аутентификации «No Authentication».

При использовании аутентификации «Individual User Accounts» был бы сгенерирован код для хранения и загрузки пользователей в БД посредством ASP.NET Identity, EF Core и localdb. Что является совершенно избыточным в рамках данной статьи, даже несмотря на наличие легковесного EntityFrameworkCore.InMemory решения для тестирования. Более того, нам в принципе не потребуется библиотека аутентификации ASP.NET Identity. Получение principal для авторизации можно самостоятельно эмулировать in-memory, а сериализация principal в cookie возможна стандартными средствами Core MVC. Это всё, что нужно для нашего тестирования.

Если хочется использовать ASP.NET Identity с in-memory хранилищем пользователей

Для эмуляции хранилища пользователей достаточно открыть Startup.cs и зарегистрировать сервисы-заглушки во встроенном DI-контейнере:

public void ConfigureServices(IServiceCollection services) < //включаем Identity services.AddIdentity(); //регистрируем хранилище services.AddTransient, FakeUserStore>(); services.AddTransient, FakeRoleStore>(); >

Кстати, мы всего лишь проделали ту же работу, что проделал бы вызов AddEntityFrameworkStores :

services.AddIdentity() .AddEntityFrameworkStores();

Начнем с авторизации пользователя на сайте: на GET /Home/Login нарисуем форму-заглушку, добавим кнопку для отправки пустой формы на сервер. На POST /Home/Login вручную создадим principal, identity и claim (в реальном приложении эти данные были бы получены из БД). Вызов HttpContext.Authentication.SignInAsync сериализует principal и поместит его в зашифрованный cookie, который в свою очередь будет прикреплен к ответу веб-сервера и сохранен на стороне клиента:

Создание principal-заглушки при входе пользователя на сайт

[HttpGet] [AllowAnonymous] public IActionResult Login(string returnUrl = null) < ViewData["ReturnUrl"] = returnUrl; return View(); >[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Login(LoginViewModel vm, string returnUrl = null) < //TODO: проверка пароля, загрузка пользователя из БД, и т.д. и т.п. var claims = new List< new Claim(ClaimTypes.Name, "Fake User"), new Claim("age", "25", ClaimValueTypes.Integer) >; var identity = new ClaimsIdentity("MyCookieMiddlewareInstance"); identity.AddClaims(claims); var principal = new ClaimsPrincipal(identity); await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal, new AuthenticationProperties < ExpiresUtc = DateTime.UtcNow.AddMinutes(20) >); _logger.LogInformation(4, "User logged in."); return RedirectToLocal(returnUrl); >

Включим cookie-аутентификацию в методе Startup.Configure(app):

app.UseCookieAuthentication(new CookieAuthenticationOptions() < AuthenticationScheme = "MyCookieMiddlewareInstance", CookieName = "MyCookieMiddlewareInstance", LoginPath = new PathString("/Home/Login/"), AccessDeniedPath = new PathString("/Home/AccessDenied/"), AutomaticAuthenticate = true, AutomaticChallenge = true >);

Этот код с небольшими модификациями будет основой для всех последующих примеров.

Атрибут Authorize и политики доступа

Атрибут [Authorize] никуда не делся из MVC. По-прежнему, при маркировке controller/action этим атрибутом — доступ внутрь получит только авторизованный пользователь. Вещи становятся интереснее, если дополнительно указать название политики (policy) — некоторого требования к claim пользователя:

[Authorize(Policy = "age-policy")] public IActionResult About()

Политики создаются в уже известном нам методе Startup.ConfigureServices :

services.AddAuthorization(options => < options.AddPolicy("age-policy", x =>< x.RequireClaim("age"); >); >);

Такая политика устанавливает, что попасть на страницу About сможет только авторизованный пользователь с claim-ом «age», при этом значение claim не учитывается. В следующем разделе, мы перейдем к примерам посложнее (наконец-то!), а сейчас разберемся, как это работает внутри?

[Authorize] — атрибут маркерный, сам по себе логики не содержащий. Нужен он лишь для того, чтобы указать MVC, к каким controller/action следует подключить AuthorizeFilter — один из встроенных фильтров Core MVC. Концепция фильтров та же, что и в предыдущих версиях фреймворка: фильтры выполняются последовательно, и позволяют выполнить код до и после обращения к controller/action. Важное отличие от middleware: фильтры имеют доступ к специфичному для MVC контексту (и выполняются, естественно, после всех middleware). Впрочем, грань между filter и middleware весьма расплывчата, так как вызов middleware возможно встроить в цепочку фильтров при помощи атрибута [MiddlewareFilter].

Вернемся к авторизации и AuthorizeFilter. Самое интересное происходит в его методе OnAuthorizationAsync:

  1. Из списка политик выбирается нужная на основе указанного в атрибуте [Authorize] значения (либо берется AuthorizationPolicy — политика по-умолчанию, содержащая всего одно требование с говорящим названием — DenyAnonymousAuthorizationRequirement.
  2. Выполняется проверка, соответствует ли набор из identity и claim-ов пользователя (например, полученных ранее из cookies запроса) требованиям политики.

Надеюсь, приведенные ссылки на исходный код дали вам представление об внутреннем устройстве фильтров в Core MVC.

Настройки политик доступа

Создание политик доступа через рассмотренный выше fluent-интерфейс не дает той гибкости, которая требуется в реальных приложениях. Конечно, можно явно указать допустимые значения claim через вызов RequireClaim(«x», params values) , можно скомбинировать через логическое И несколько условий, вызвав RequireClaim(«x»).RequireClaim(«y») . Наконец, можно навесить на controller и action разные политики, что, впрочем, приведет к той же комбинации условий через логическое И. Очевидно, что необходим более гибкий механизм создания политик, и он у нас есть: requirements и handlers.

services.AddAuthorization(options => < options.AddPolicy("age-policy", policy =>policy.Requirements.Add(new AgeRequirement(42), new FooRequirement())); >);

Requirement — не более чем DTO для передачи параметров в соответствующий handler, который в свою очередь имеет доступ к HttpContext.User и волен налагать любые проверки на principal и содержащиеся в нем identity/claim. Более того, handler может получать внешние зависимости через встроенный в Core MVC DI-контейнер:

Пример requirement и handler

public class MinAgeRequirement : IAuthorizationRequirement < public MinAgeRequirement(int age) < Age = age; >public int Age < get; private set; >> public class MinAgeHandler : AuthorizationHandler  < public MinAgeHandler(IFooService fooService) < // fooService будет передан через DI >protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinAgeRequirement requirement) < bool hasClaim = context.User.HasClaim(c =>c.Type == "age"); bool hasIdentity = context.User.Identities.Any(i => i.AuthenticationType == "MultiPass"); string claimValue = context.User.FindFirst(c => c.Type == "age").Value; if (int.Parse(claimValue) >= requirement.Age) < context.Succeed(requirement); >else < context.Fail(); >return Task.CompletedTask; > >

Регистрируем сам handler в Startup.ConfigureServices(), и он готов к использованию:

services.AddSingleton();

Handler-ы возможно сочетать как через AND, так и через OR. Так, при регистрации нескольких наследников AuthorizationHandler , все они будут вызваны. При этом вызов context.Succeed() не является обязательным, а вызов context.Fail() приводит к общему отказу в авторизации вне зависимости от результата других handler. Итого, мы можем комбинировать между собой рассмотренные механизмы доступа следующим образом:

  • Policy: AND
  • Requirement: AND
  • Handler: AND / OR.

Resource-based авторизация

Как уже говорилось ранее, policy-based авторизация выполняется Core MVC в filter pipeline, т.е. ДО вызова защищаемого action. Успех авторизации при этом зависит только от пользователя — либо он обладает нужными claim, либо нет. А что, если необходимо учесть также защищаемый ресурс и его свойства, получить какие данные из внешних источников? Пример из жизни: защищаем action вида GET /Orders/ , считывающий по id строку с заказом из БД. Пусть наличие у пользователя прав на конкретный заказ мы сможем определить только после получения этого заказа из БД. Это автоматически делает непригодными рассмотренные ранее аспектно-ориентированные сценарии на основе фильтров MVC, выполняемых перед тем, как пользовательский код получает управление. К счастью, в Core MVC есть способы провести авторизацию вручную.

Для этого, в контроллере нам потребуется реализация IAuthorizationService . Получим ее, как обычно, через внедрение зависимости в конструктор:

public class ResourceController : Controller < IAuthorizationService _authorizationService; public ResourceController(IAuthorizationService authorizationService) < _authorizationService = authorizationService; >>

Затем создадим новую политику и handler:

options.AddPolicy("resource-allow-policy", x => < x.AddRequirements(new ResourceBasedRequirement()); >); public class ResourceHandler : AuthorizationHandler  < protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, ResourceBasedRequirement requirement, Order order) < // TODO: проверка, имеет ли пользователь права на действия с заказом if (true) context.Succeed(requirement); return Task.CompletedTask; >>

Наконец, проверяем пользователя + ресурс на соответствие нужной политике внутри action (заметьте, атрибут [Authorize] больше не нужен):

public async Task Allow(int id) < Order order = new Order(); //получим ресурс из БД if (await _authorizationService.AuthorizeAsync(User, order, "my-resource-policy")) < return View(); >else < //вернем 401 или 403 в зависимости от состояния пользователя return new ChallengeResult(); >>

У метода IAuthorizationService.AuthorizeAsync есть перегрузка, принимающая список из requirement — вместо названия политики:

Task AuthorizeAsync( ClaimsPrincipal user, object resource, IEnumerable requirements);

Что позволяет еще более гибко настраивать права доступа. Для демонстрации, используем преопределенный OperationAuthorizationRequirement (да, этот пример перекочевал в статью прямо с docs.microsoft.com):

public static class Operations < public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement < Name = "Create" >; public static OperationAuthorizationRequirement Read = new OperationAuthorizationRequirement < Name = "Read" >; public static OperationAuthorizationRequirement Update = new OperationAuthorizationRequirement < Name = "Update" >; public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement < Name = "Delete" >; >

что позволит вытворять следующие вещи:

_authorizationService.AuthorizeAsync( User, resource, Operations.Create, Operations.Read, Operations.Update);

В методе HandleRequirementAsync(context, requirement, resource) соответствующего handler — нужно лишь проверить права соответственно операции, указанной в requirement.Name и не забыть вызвать context.Fail() если пользователь провалил авторизацию:

protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, Order order) < string operationName = requirement.Name; // Проверка, имеет ли пользователь права на действия с заказом if(true) context.Succeed(requirement); return Task.CompletedTask; >

Handler будет вызван столько раз, сколько requirement вы передали в AuthorizeAsync и проверит каждый requirement по-отдельности. Для единовременной проверки всех прав на операции за один вызов handler — передавайте список операций внутри requirement, например так:

 new OperationListRequirement(new[] < Ops.Read, Ops.Update >)

На этом обзор возможностей resource-based авторизации закончен, и самое время покрыть наши handler-ы тестами:

[Test] public async Task MinAgeHandler_WhenCalledWithValidUser_Succeed() < var requirement = new MinAgeRequirement(24); var user = new ClaimsPrincipal(new ClaimsIdentity(new List< new Claim("age", "25") >)); var context = new AuthorizationHandlerContext(new [] < requirement >, user, resource: null); var handler = new MinAgeHandler(); await handler.HandleAsync(context); Assert.True(context.HasSucceeded); >

Авторизация в Razor-разметке

Выполняемая непосредственно в разметке проверка прав пользователя может быть полезна для скрытия элементов UI, к которым пользователь не должен иметь доступ. Конечно же, во view можно передать все необходимые флаги через ViewModel (при прочих равных я за этот вариант), либо обратиться напрямую к principal через HttpContext.User:

Возраст: @User.GetClaimValue("age")

Если вам интересно, то view наследуются от RazorPage класса, а прямой доступ к HttpContext из разметки возможен через свойство @Context .

С другой стороны, мы можем использовать подход из предыдущего раздела: получить реализацию IAuthorizationService через DI (да, прямо во view) и проверить пользователя на соответствие требованиям нужной политики:

@inject IAuthorizationService AuthorizationService @if (await AuthorizationService.AuthorizeAsync(User, "my-policy"))

Не пытайтесь использовать в нашем тестовом проекте вызов SignInManager.IsSignedIn(User) (используется в шаблоне веб-приложения с типом аутентификации Individual User Accounts). В первую очередь потому, что мы не используем библиотеку аутентификации Microsoft.AspNetCore.Identity , к которой этот класс принадлежит. Сам метод внутри не делает ничего, помимо проверки наличия у пользователя identity с зашитым в коде библиотеки именем.

Permission-based авторизация. Свой фильтр авторизации

Декларативное перечисление всех запрашиваемых операций (в первую очередь из числа CRUD) при авторизации пользователя, такое как:

var requirement = OperationListRequirement(new[] < Ops.FooAction, Ops.BarAction >); _authorizationService.AuthorizeAsync(User, resource, requirement);

… имеет смысл, если в вашем проекте построена система персональных разрешений (permissions): имеется некий набор из большого числа высокоуровневых операций бизнес-логики, есть пользователи (либо группы пользователей), которым были в ручном режиме выданы права на конкретные операции с конкретным ресурсом. К примеру, у Васи есть права «драить палубу», «спать в кубрике», а Петя может «крутить штурвал». Хорош или плох такой паттерн — тема для отдельной статьи (лично я от него не в восторге). Очевидная проблема данного подхода: список операций легко разрастается до нескольких сотен даже не в самой большой системе.

Ситуация упрощается, если для авторизации нет нужды учитывать конкретный экземпляр защищаемого ресурса, и наша система обладает достаточной гранулярностью, чтобы просто навесить на весь метод атрибут со списком проверяемых операций, вместо сотен вызовов AuthorizeAsync в защищаемом коде. Однако, использование авторизации на основе политик [Authorize(Policy = «foo-policy»)] приведет к комбинаторному взрыву числа политик в приложении. Почему бы не использовать старую добрую role-based авторизацию? В примере кода ниже, пользователю необходимо быть членом всех указанных ролей для получения доступа к FooController:

[Authorize(Roles = "PowerUser")] [Authorize(Roles = "ControlPanelUser")] public class FooController : Controller

Подобное решение так же может не дать достаточной детализации и гибкости для системы с большим количеством permissions и их возможных комбинаций. Дополнительные проблемы начинаются, когда нужна и role-based и permission-based авторизация. Да и семантически, роли и операции — разные вещи, хотелось бы обрабатывать их авторизацию отдельно. Решено: пишем свою версию атрибута [Authorize] ! Продемонстрирую конечный результат:

[AuthorizePermission(Permission.Foo, Permission.Bar)] public IActionResult Edit()

Начнем с создания enum для операций, requirement и handler для проверки пользователя:

Скрытый текст

public enum Permission < Foo, Bar >public class PermissionRequirement : IAuthorizationRequirement < public Permission[] Permissions < get; set; >public PermissionRequirement(Permission[] permissions) < Permissions = permissions; >> public class PermissionHandler : AuthorizationHandler  < protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, PermissionRequirement requirement) < //TODO: ваш код проверки, есть ли у пользователя права на эти операции if (requirement.Permissions.Any()) < context.Succeed(requirement); >return Task.CompletedTask; > >

Ранее я рассказывал, что атрибут [Authorize] сугубо маркерный и нужен для применения AuthorizeFilter . Не будем бороться с существующей архитектурой, поэтому напишем по аналогии собственный фильтр авторизации. Поскольку список permissions у каждого action свой, то:

  1. Необходимо создавать экземпляр фильтра на каждый вызов;
  2. Невозможно напрямую создать экземпляр через встроенный DI-контейнер.

К счастью, в Core MVC эти проблемы легко разрешимы при помощи атрибута [TypeFilter]:

[TypeFilter(typeof(PermissionFilterV1), new object[] < new[] < Permission.Foo, Permission.Bar >>)] public IActionResult Index()

PermissionFilterV1

public class PermissionFilterV1 : Attribute, IAsyncAuthorizationFilter < private readonly IAuthorizationService _authService; private readonly Permission[] _permissions; public PermissionFilterV1(IAuthorizationService authService, Permission[] permissions) < _authService = authService; _permissions = permissions; >public async Task OnAuthorizationAsync(AuthorizationFilterContext context) < bool ok = await _authService.AuthorizeAsync( context.HttpContext.User, null, new PermissionRequirement(_permissions)); if (!ok) context.Result = new ChallengeResult(); >>

Мы получили полностью работающее, но безобразно выглядящее решение. Для того, чтобы скрыть детали реализации нашего фильтра от вызывающего кода, нам и пригодится атрибут [AuthorizePermission] :

public class AuthorizePermissionAttribute : TypeFilterAttribute < public AuthorizePermissionAttribute(params Permission[] permissions) : base(typeof(PermissionFilterV2)) < Arguments = new[] < new PermissionRequirement(permissions) >; Order = Int32.MaxValue; > >
[AuthorizePermission(Permission.Foo, Permission.Bar)] [Authorize(Policy = "foo-policy")] public IActionResult Index()

Обратите внимание: фильтры авторизации работают независимо, что позволяет сочетать их друг с другом. Порядок выполнения нашего фильтра в общей очереди можно скорректировать при помощи свойства AuthorizePermissionAttribute.Order .

Дополнительные материалы для чтения по теме (также приветствуются ваши ссылки для включения в список):

  • Официальная документация на docs.microsoft.com.
  • Цикл статей по безопасности ASP.NET Core в блоге Andrew Lock | .NET Escapades. Интересный блог в целом.

На этом обзор авторизации в ASP.NET Core MVC завершен. Большая часть материала применима и к WebAPI. Желающим воспроизвести примеры из статьи я рекомендую воспользоваться демонстрационным проектом. В следующей статье (я надеюсь) мы защитим веб-сайт и публичный API при помощи выделенного сервера аутентификации.

  • asp.net core mvc
  • authorization
  • авторизация

Перевод «key money» на русский

The Panel has considered two claims for the loss of key money that raise new verification and valuation issues.

Группа рассмотрела две претензии в отношении потери арендного залога, в связи с которыми возникают новые вопросы проверки и стоимостной оценки.

The largest category of «other» losses claimed is for key money and goodwill.
Крупнейшую категорию заявленных «прочих» потерь составляют арендный залог и «гудвилл».

A number of the claimants sought compensation for the loss of key money, that is money paid for the right to lease particular premises.

Ряд заявителей просили о компенсации потери арендного залога, т.е. денежных средств, выплаченных за право аренды конкретных помещений.

As part of the legal review, the Panel also requires the claimant to provide evidence of efforts to mitigate the key money or goodwill loss.

В ходе юридического анализа Группа также требует от заявителя представить подтверждение его усилий по сведению к минимуму потерь, связанных с уплатой арендного залога или обеспечивающей репутацию суммы.

This decision was based on the fact that the Kuwaiti Government does not regulate the payment of key money and therefore the letter could only be viewed as a supporting witness statement.

Это решение было мотивировано тем, что правительство Кувейта не регламентирует арендного залога, и поэтому данное письмо могло бы рассматриваться лишь как вторичное свидетельство.

Such an item cannot be considered as either key money (that is, the right to lease particular premises) or as goodwill (which is the value of the reputation of the business).

Подобную позицию нельзя рассматривать ни в качестве арендного залога (т.е. права на аренду конкретных помещений), ни «гудвилла» (который представляет собой стоимость репутации предприятия).

These losses included loss of tangible property, loss of profit, loss of goodwill and key money and the individual’s claim for loss of equity in the «E4» claimant company.

Эти потери включали в себя потерю материального имущества, упущенную выгоду, потерю «гудвилла» и арендного залога, а также индивидуальную претензию в связи с потерей долевого участия в компании-заявителе претензии «Е4».

The audited accounts for the years ended 31 December 1988 and 1989 included neither the value of the key money nor the value of the IATA licence.

В ревизованных счетах за периоды, заканчивающиеся 31 декабря 1988 года и 1989 года, не фигурировали ни стоимость арендного залога, ни стоимость лицензии ИАТА.

The individual claimant that was identified as overlapping with the «E4″claimant Graphic Arts Supplies & Services Co. asserted losses of tangible property, goodwill and key money that had not been claimed by the «E4″claimant.

«, испрашивает компенсацию потерь материального имущества,»гудвилла» и арендного залога, которые не указывались заявителем претензии «Е4».

In relation to Selwan Trading Co. W.L.L., the Panel decided that the claimant had established that, as at 2 August 1990, the company owned the key money that had been paid in 1976 by the unincorporated forerunner of the company.

В связи с претензией компании «Селван трейдинг ко у.л.л.» Группа решила, что заявитель продемонстрировал, что по состоянию на 2 августа 1990 года у компании имелась задолженность в сумме арендного залога, который был выплачен в 1976 году неинкорпорированным предшественником этой компании.

When you are compensated in carats, properly, then you definitely are actually referring to some key money.

Когда вы платите в каратах, хорошо, то вы действительно говорите о некоторых большие деньги.
This key money would need to be added to the selling price to give the final value of the property.

Эту «входную плату» необходимо будет добавить к цене продажи, чтобы получить окончательную стоимость имущества.

This article summarises some of the FCA’s key money laundering updates in 2019.

Данная статья описывает основные обновления FCA по отмыванию денег, которые были приняты в 2019 году.

Hence one of Latvia’s key money laundering risks remains the vulnerability of CIS countries to economic crime, especially corruption.

Следовательно, одним из основных рисков, связанных с отмыванием денег (ML) в Латвии, остается уязвимость стран СНГ к экономической преступности, особенно коррупции.

This legal test focuses on claims for goodwill or key money that are not documented by reference to an historical expenditure or other verifiable evidence of value.

Эта юридическая проверка особо сосредоточена на претензиях в связи с обеспечивающими репутацию выплатами или арендным залогом, которые не отражены в расходной документации за соответствующий период или в других финансовых документах, которые могут быть проверены.

Sixth instalment claimants also submitted claims for uncollected receivables, goodwill, key money, contracts and other losses not specifically itemised on the D9 page of the claim form.

Заявители претензий в составе шестой партии также подали претензии в связи с невостребованной дебиторской задолженностью, ущербом деловой репутации, потерей залоговых сумм, невыполненными контрактами и другими потерями, конкретно не перечисленными в форме претензии на странице «D9».

In any case, there are in like manner other likewise key money related news releases that incredibly influence the US economy.

Однако есть и другие не менее важные экономические новостные выпуски, которые оказывают большое влияние на экономику США.

The Panel reviewed several claims for goodwill and key money losses filed in relation to businesses that are still operating in Kuwait.

Группа рассмотрела несколько претензий о компенсации потерь неосязаемых активов и авансов по арендной плате, понесенных предприятиями, по-прежнему действующими в Кувейте.

The review also assesses whether any aspect of the key money or goodwill claim is unduly speculative.

В ходе анализа также рассматривается вопрос о том, не является ли какой-либо аспект претензии в связи с арендным залогом или обеспечивающей репутацию выплатой необоснованно завышенным.

Возможно неприемлемое содержание

Примеры предназначены только для помощи в переводе искомых слов и выражений в различных контекстах. Мы не выбираем и не утверждаем примеры, и они могут содержать неприемлемые слова или идеи. Пожалуйста, сообщайте нам о примерах, которые, на Ваш взгляд, необходимо исправить или удалить. Грубые или разговорные переводы обычно отмечены красным или оранжевым цветом.

Зарегистрируйтесь, чтобы увидеть больше примеров. Это просто и бесплатно
Ничего не найдено для этого значения.
Предложить пример
Больше примеров Предложить пример

Новое: Reverso для Windows

Переводите текст из любого приложения одним щелчком мыши .

Скачать бесплатно
Перевод голосом, функции оффлайн, синонимы, спряжение, обучающие игры

Результатов: 40 . Точных совпадений: 40 . Затраченное время: 72 мс

Помогаем миллионам людей и компаний общаться более эффективно на всех языках.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *