Не удается получить текущего пользователя или авторизоваться - PullRequest
0 голосов
/ 29 июня 2018

Работа над приложением Angular 2 / ASP.NET Core 2.1. После входа в систему я могу console.log токен JWT из внешнего интерфейса, но когда я пытаюсь получить доступ к контроллеру (AccountsController.cs) с атрибутом [Authorize], я получаю ошибку 401. Если я удаляю атрибут и пытаюсь получить текущего пользователя, используя var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);, я немедленно отправляюсь обратно во внешний интерфейс и получаю сообщение об ошибке через распознаватель.

Похоже, что данные текущего пользователя не отправляются на сервер с запросом. Или это не хранится? Или, может быть, я не получаю доступ правильно?

счета-list.resolver.ts

import { Resolve, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Account } from '../../_models/account';
import { Injectable } from '@angular/core';
import { AccountService } from '../../_services/account.service';
import { AlertifyService } from '../../_services/alertify.service';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';

@Injectable()
export class AccountListResolver implements Resolve<Account[]> {
  pageSize = 5;
  pageNumber = 1;

  constructor(private accountService: AccountService,
    private router: Router,
    private alertify: AlertifyService) {
  }

  resolve(route: ActivatedRouteSnapshot): Observable<Account[]> {
    return this.accountService.getAccounts(this.pageNumber, this.pageSize).catch(error => {
      this.alertify.error('Problem retrieving data');
      this.router.navigate(['/dashboard']);
      return Observable.of(null);
    });
  }
}


account.service.ts

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { Account } from '../_models/account';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { PaginatedResult } from '../_models/pagination';
import { HttpClient, HttpParams } from '@angular/common/http';

@Injectable()
export class AccountService {
  baseUrl = environment.apiUrl;

  constructor(private authHttp: HttpClient) { }

  getAccounts(page?, itemsPerPage?, accountParams?: any) {
    const paginatedResult: PaginatedResult<Account[]> = new PaginatedResult<Account[]>();
    let params = new HttpParams();

    if (page != null && itemsPerPage != null) {
      params = params.append('pageNumber', page);
      params = params.append('pageSize', itemsPerPage);
    }

    // if (accountParams != null) {
    //   params = params.append('paramName', accountParams.paramName);
    // }

    return this.authHttp
      .get<Account[]>(this.baseUrl + 'accounts', { observe: 'response', params })
      .map(response => {
        paginatedResult.result = response.body;
        if (response.headers.get('Pagination') != null) {
          paginatedResult.pagination = JSON.parse(response.headers.get('Pagination'));
        }

        return paginatedResult;
      });
  }
}


AccountsController

[Authorize]
[Route("api/[controller]")]
public class AccountsController : Controller
{
    private readonly IBaseRepository _repo;
    private readonly IMapper _mapper;

    public AccountsController(IBaseRepository repo, IMapper mapper)
    {
        _mapper = mapper;
        _repo = repo;
    }

    [HttpGet]
    public async Task<IActionResult> GetAccounts([FromQuery] AccountParams accountParams)
    {
        var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
        //^^^WHERE IT BREAKS WHEN AUTHORIZATION ATTRIBUTE IS REMOVED

        //code to generate list of accounts to return
        accountParams.UserId = currentUserId;

        var accounts = await _repo.GetAccounts(accountParams);

        var accountsToReturn = _mapper.Map<IEnumerable<AccountForListDto>>(accounts);

        Response.AddPagination(accounts.CurrentPage, accounts.PageSize, accounts.TotalCount, accounts.TotalPages);

        return Ok(accountsToReturn);
    }
}


** EDIT **

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);

    services.AddDbContext<DataContext>(x => x
        .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b =>
            b.MigrationsAssembly(("MyApp.App")))
        .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));

    services.AddMvc()
        .AddJsonOptions(opt =>
        {
            opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });

    services.AddTransient<Seed>();

    services.AddCors();

    services.AddAutoMapper();

    services.AddScoped<IAuthRepository, AuthRepository>();

    services.AddScoped<IBaseRepository, BaseRepository>();

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

    services.AddScoped<LogUserActivity>();
}

public void ConfigureDevelopmentServices(IServiceCollection services)
{
    var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);

    services.AddDbContext<DataContext>(x => x
        .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b =>
            b.MigrationsAssembly(("MyApp.App")))
        .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)));

    services.AddMvc()
        .AddJsonOptions(opt =>
        {
            opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });

    services.AddTransient<Seed>();

    services.AddCors();

    services.AddAutoMapper();

    services.AddScoped<IAuthRepository, AuthRepository>();

    services.AddScoped<IBaseRepository, BaseRepository>();

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

    services.AddScoped<LogUserActivity>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(builder =>
        {
            builder.Run(async context =>
            {
                context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;

                var error = context.Features.Get<IExceptionHandlerFeature>();
                if (error != null)
                {
                    context.Response.AddApplicationError(error.Error.Message);
                    await context.Response.WriteAsync(error.Error.Message);
                }
            });
        });
    }

    app.ConfigureSwagger(Assembly.GetExecutingAssembly());

    app.UseCors(x => x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
    app.UseDefaultFiles();
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseSpaStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });

    app.UseSpa(spa =>
    {
        // To learn more about options for serving an Angular SPA from ASP.NET Core,
        // see https://go.microsoft.com/fwlink/?linkid=864501

        spa.Options.SourcePath = "ClientApp";

        if (env.IsDevelopment())
        {
            spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
            //spa.UseAngularCliServer(npmScript: "start");
        }
    });
}

1 Ответ

0 голосов
/ 29 июня 2018

Вы добавили обработчик авторизации JWT?

В вашем стартапе.cs

  1. Есть ли app.UseAuthentication() в методе Configure?
  2. Это раньше app.UseMvc()?
  3. Есть ли app.AddAuthentication() в вашем ConfigureServices методе?
  4. Это раньше app.AddMvc()?
  5. Есть ли вызов AddJwtBearer() в вашем ConfigureServices методе зависания от звонка на AddAuthentication()?
  6. У вас есть нужные ключи в опциях для службы JwtBearer?
  7. Если JwtBearer не является вашим единственным механизмом аутентификации (например, вы также добавили Identity), указываете ли вы имя схемы для носителя в вашем атрибуте Authorize?

Из вашей конфигурации похоже, что вам не хватает app.UseAuthentication () в методе настройки.

Так что вам нужно поставить его перед app.UseMvc () вот так;

app.UseSpaStaticFiles();
app.UseAuthentication()
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...