ASP. Net Core 3.0 объединенные роли - PullRequest
0 голосов
/ 10 марта 2020

в моем текущем веб-приложении я аутентифицирую пользователя с утверждением «customRole» (плюс его значение) и использую атрибут «Авторизовать», чтобы разрешить / запретить доступ к действиям. Все работает хорошо до тех пор, пока пользователь не получит более одного утверждения одного и того же типа, в доступе все время будет отказано, и при отладке я заметил, что для типа "customRole" было создано только одно утверждение, и его значение изменилось на объединенную строку с оба значения.

Я ожидал двух утверждений одного типа, но каждое из которых имело разные значения. Я использую AS PNET .Core 3.0 с IdentityServer4, но из того, что написано здесь , IdentityServer4 не проблема.

Например, я добавляю претензии, как так далее сторона IdentityServer:

uClaims.Add(new Claim("customRole", "superadmin"));
uClaims.Add(new Claim("customRole", "simpleadmin"));

Но когда я попадаю в клиентское приложение, я получаю утверждение примерно так:

customRole = ["superadmin","simpleadmin"]

Это ломает все логики c за атрибутом для ролей что я использую в действиях для клиентского приложения:

[Authorize(Roles = "superadmin")]

Я попытался следовать тому, что обсуждалось в предыдущей ссылке ( здесь ), но проблема не устранена.

Что-то пропущено, поэтому заявки разделяются, а не объединяются с разными значениями? или использовать авторизацию другим способом, который допускает массив значений?

Следует также упомянуть, что я начал работать с Asp .NetCore, IdentityServer4 и Roles впервые за последний месяц. м в кривой обучения.

Спасибо за ваше время, ура

Ответы [ 3 ]

0 голосов
/ 11 марта 2020

Это связано с тем, что атрибут [Authorize(Roles="superadmin")] проверяет, содержит ли текущий идентификатор утверждение типа ClaimsIdentity.RoleClaimType (http://schemas.microsoft.com/ws/2008/06/identity/claims/role), где значение утверждения равно значению, указанному параметром Roles.

superadmin и simpleadmin имеют тип customRole, а не по умолчанию http://schemas.microsoft.com/ws/2008/06/identity/claims/role. Таким образом, авторизация не проходит. Вы можете настроить промежуточное ПО AddOpenIdConnect для установки RoleClaimType:

JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "http://localhost:5000";
    options.RequireHttpsMetadata = false;

    options.ClientId = "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = "code";

    options.SaveTokens = true;

    options.Scope.Add("api1");
    options.Scope.Add("offline_access");
    options.TokenValidationParameters.RoleClaimType = "customRole";   //add this line

});

, чтобы MVC проверял утверждения customRole при запуске [Authorize(Roles="superadmin")].

0 голосов
/ 11 марта 2020

я выяснил причину почему. Я использовал при запуске

.AddOpenIdConnect(IdentityServerConstants.ProtocolTypes.OpenIdConnect, options => { options.ClaimActions.MapUniqueJsonKey("customRole", "customRole"); }

вместо

.AddOpenIdConnect(IdentityServerConstants.ProtocolTypes.OpenIdConnect, options => { options.ClaimActions.MapJsonKey("customRole", "customRole"); }

Теперь все претензии одного типа разделяются и не объединяется как один внутри clientApp. Я думаю, что я использовал не тот маппер, потому что я скопировал из одного из краткого учебного пособия identityServer4 (или примеров других людей, что гуглил вокруг) :) Надеюсь, мой собственный ответ не дает другим терять время, чтобы понять, как все работает, как они должны :)

@ Nan Yu: Исправление параметров RoleClaimType решает проблему использования type = "customRole" вместо значения по умолчанию, но нескольких утверждений одного типа все еще соединены. Но из вашего комментария я узнал что-то новое, настраивая roleClaimType, спасибо вам за это

@ Mehrdad При использовании конфигурации, заявка не указана в контексте, только утверждения типа "nbf", "iss", "aud" et c, отображаются, пользовательские не отображаются здесь (не знаю почему). Но, тем не менее, я бездельничал и обнаружил, что, как вы сказали, можно добавить сюда дополнительные требования, так что это может пригодиться в будущем, спасибо за обмен информацией

0 голосов
/ 11 марта 2020

Вы можете изменить своего Принципала после проверки подлинности и преобразовать это требование в несколько.

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
          ...
            options.Events = new JwtBearerEvents();
            options.EventsType = typeof(CustomJwtBearerEvents);
        });

        public class CustomJwtBearerEvents : JwtBearerEvents
        {
           public override async Task TokenValidated(TokenValidatedContext context)
           {
              var claims = context.Principal.Claims.ToList();
//write your code
                  claims.Add(new Claim("key", "value"));
                  context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, 
    "Bearer"));        }
        }

найти свое конкретное c утверждение ('customclaim') и проверить его значение, если оно содержит более одного затем добавьте одну заявку для каждого значения.

...