Авторизация не работает после добавления токена JWT в ASP .Net Core 2.2 - PullRequest
0 голосов
/ 01 ноября 2019

Я учусь использовать аутентификацию токена JWT в ASP. У меня есть простой веб-сайт с операциями CRUD и репозитарием, я добавил функциональность регистрации / входа в систему, и у меня есть одна роль «Администратор», которая является суперпользователем. Обычно, вот как я проверяю, вошел ли пользователь в систему с правами администратора:

bool admin = User.IsInRole(Constants.ADMIN_ROLE);

Эта функция работала нормально, пока я не добавил аутентификацию JWT в свое приложение. Теперь, входя в систему с моей учетной записью администратора (добавленной в БД вручную), я никогда не получаю правильное значение. Когда я пытаюсь запросить пользователя, я получаю NULL:

var user = await _userManager.GetUserAsync(HttpContext.User)

Это мои ConfigureServices в Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        services.AddIdentity<MyUser, MyRole>()
            .AddEntityFrameworkStores<MyContext>()
            .AddRoles<MyRole>();


        services.AddDbContext<MyContext>(builder =>
        {
            builder.UseSqlServer(Configuration["ConnectionStrings"]);
        });

        // repo code here ommitted for clarity

        var appSettingsSection = Configuration.GetSection("AppSettings");
        services.Configure<AppSettings>(appSettingsSection);

        var appSettings = appSettingsSection.Get<AppSettings>();
        var key = Encoding.ASCII.GetBytes(appSettings.Secret);
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
            };

        });

    }

И это мой класс Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseMvc();
        app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    }

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

1 Ответ

0 голосов
/ 01 ноября 2019

Я полностью реализовал аутентификацию в JWT.

Я добавил новую заявку в свой токен во время создания дескриптора токена:

                  ... 
 Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, userId.ToString()),
                new Claim(ClaimTypes.Role, roleId)
            }),
                  ...

и добавил информацию, связанную сРоль внутри (в моем случае я использовал идентификатор роли, чтобы сделать ее менее описательной, если кому-то удастся ее расшифровать)

var roles = await _userManager.GetRolesAsync(userInDb);
var userRoleId = await _roleManager.FindByNameAsync(roles.First());
                       ...
return Ok(_tokenService.GenerateToken(userInDb.Id, userRoleId.Id.ToString()));

Затем решить, является ли пользователь администратором или нет, так же просто, как получитьсоответствующее значение из токена:

private async Task<bool> IsUserAdmin()
{
    var roleId = Guid.Parse(User.Claims.FirstOrDefault(e => e.Type == "role").Value);
    var adminId = (await _roleManager.FindByNameAsync(Constants.ADMIN_ROLE))?.Id;     
    return roleId == adminId;
}

Хотя это, кажется, работает, я все еще думаю, что могут быть более эффективные (менее хакерские) способы сделать это, которые задействуют лучшую интеграцию JWT в идентичность, так что если кто-тоЯ могу предложить более краткое решение, я рад принять его в качестве ответа вместо моего решения.

...