Я пытаюсь получить проверку подлинности токена в приложении ядра .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. И это запрос, который не аутентифицирован. Поэтому вопрос заключается в том, как заставить систему собрать токен из параметра запроса и выполнить аутентификацию.
Это также приводит к вопросу, почему я хотел бы видеть свои токены в параметре запроса. Во-первых, это приводит к тому, что они отображаются в журнале, что не совсем функция безопасности. Может быть, мне все-таки лучше делать простые веб-сокеты ..