Как сделать аутентификацию токена в .Net Core 2.1 с SignalR - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь получить проверку подлинности токена в приложении ядра .net для работы с signalR. Идея заключается в том, что веб-интерфейс инициирует подключение SignalR к бэкэнду. Клиент Javascript signalR добавляет токен к соединителю SignalR следующим образом:

  const options: IHttpConnectionOptions  = {
  accessTokenFactory : (): Promise<string> => {
    return new Promise<string>((resolve) => {
      this.log('providing token');
      resolve(this.login.getToken());
    });
  }
};

this.connection = new HubConnectionBuilder()
  .withUrl('/mqtthub', options)
  .configureLogging(LogLevel.Debug)
  .build();

Пока все работает нормально, я на самом деле вижу, как токен появляется при согласовании соединения signalR. Здесь я начинаю удивляться. Я могу заставить конечную точку SignalR проверить токен, но проверено или нет, соединение все равно установлено. Я бы предпочел неаутентифицированные соединения, где сразу отказались Но это имеет второстепенное значение ..

Когда я переопределяю публичную функцию OnConnectedAsync () в хабе SignalR, я не получаю аутентифицированного пользователя. И вызов метода для соединения signalR (из веб-интерфейса) завершается неудачно, потому что я использую атрибут [Authorize ("Bearer")] для своей функции в концентраторе. Я просмотрел множество примеров, но комбинация SignalR и JWT Auth кажется довольно редкой, особенно в реализации .Net Core 2.1.

Моя настройка в Startup.cs выглядит следующим образом:

    public void ConfigureServices(IServiceCollection services)
{

  services.AddSingleton<IUserData, UserData>();

  services.AddAuthentication(options =>
  {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  }).AddJwtBearer(jwtOpts => {
    jwtOpts.TokenValidationParameters = TokenValidator.DefaultValidationParameters;
    //jwtOpts.SecurityTokenValidators.Clear();
    //jwtOpts.SecurityTokenValidators.Add(new TokenValidator());
  });

  services.AddAuthorization(auth =>
  {
    auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
      .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
      .RequireAuthenticatedUser().Build());
  });


  services.AddMvc();
  services.AddSignalR();
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }
  else
  {
    app.UseExceptionHandler("/Home/Error");
    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
      ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });
  }


  app.UseStatusCodePagesWithReExecute("/");
  app.UseDefaultFiles();
  app.UseStaticFiles();

  app.UseAuthentication();
  // app.UseCors("CorsPolicy");
  app.UseMvc();

  app.UseSignalR(routes => { routes.MapHub<MQTTHub>("/mqtthub"); });

}

Я использовал собственный валидатор JWT, теперь я снова использую систему. Кажется, в проверке нет ничего плохого, поскольку я вижу, что она прошла успешно. Мне интересно, хотя, если для JWToken требуется определенный контент, позволяющий авторизовать пользователя, я видел, как в одном образце в токен была добавлена ​​целая куча претензий. Шахта имеет следующее содержание:

private string GenerateToken(string userid, string username)
{

  _iat = ToEpoch(DateTime.Now);
  _exp = ToEpoch(DateTime.Now.AddMinutes(20));

  var payload = new JwtPayload
  {
    {"iat", _iat },
    {"iss", _issuer},
    {"exp", _exp},
    {"nbf", _iat},
    {"aud", "*"},
    {"sub", userid},
    {"name", username},
    {"topicMask", $"^/{userid}/.*" },
    {"scope", _issuer},
  };

  var jwtToken = new JwtSecurityToken(_jwtHeader, payload);
  return JwtHandler.WriteToken(jwtToken);
}

К сожалению, я довольно новичок в ASP.NET и совершенно сбит с толку всеми этими промежуточными программами. Если бы кто-нибудь мог указать на то, что я пропустил ..

РЕДАКТИРОВАТЬ: Теперь я немного лучше понимаю проблему. Сначала SignalR ведет переговоры. Здесь токен входит в заголовок и Token Auth работает. Затем, когда он фактически подключает веб-сокет во втором запросе, он снова отправляет токен, но на этот раз в параметре запроса URL. И это запрос, который не аутентифицирован. Поэтому вопрос заключается в том, как заставить систему собрать токен из параметра запроса и выполнить аутентификацию.

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

1 Ответ

0 голосов
/ 25 октября 2018

Вот что нужно сделать:

1) Добавить новый класс промежуточного программного обеспечения

2) В промежуточном программном обеспечении Invoke () перенести токен авторизации из строки запроса в заголовок аутентификации запроса:

    /// <summary>
    /// Analyzes an incoming HttpContext to determine if the auth token should be taken from the query string
    /// </summary>
    /// <param name="httpContext">The HttpContext containing the request with user identity claims to analzye</param>
    /// <returns>A task to execute the next middleware component in the HTTP request processing pipeline</returns>
    public async Task Invoke(HttpContext httpContext)
    {
        var accessToken = httpContext.Request.Query["access_token"];
        if (!string.IsNullOrEmpty(accessToken))
        {
            httpContext.Request.Headers["Authorization"] = $"Bearer {accessToken}";
        }

        await next.Invoke(httpContext);
    }

3) Запустите это промежуточное ПО ПЕРЕД аутентификационным промежуточным ПО (app.UseAuthentication () в Startup.cs)

Это приведет к тому, что токен аутентификации будет доступен для промежуточного программного обеспечения аутентификации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...