Код: Выделить всё
using System.IdentityModel.Tokens.Jwt;
using baio_api.Infrastructure.Services.Interfaces;
using Microsoft.Extensions.Logging;
namespace baio_api.Common.Middlewares
{
public class TokenValidationMiddleware
{
private readonly RequestDelegate _next;
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
public TokenValidationMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory, ILogger logger)
{
_next = next;
_scopeFactory = scopeFactory;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
_logger.LogInformation("TokenValidationMiddleware invoked.");
if (!context.Request.Headers.ContainsKey("Authorization"))
{
_logger.LogWarning("Authorization header is missing.");
await _next(context);
return;
}
var token = context.Request.Headers["Authorization"].ToString().Split(" ").Last();
_logger.LogInformation($"Extracted token: {token}");
var handler = new JwtSecurityTokenHandler();
if (!handler.CanReadToken(token))
{
_logger.LogWarning("Cannot read token.");
await _next(context);
return;
}
using (var scope = _scopeFactory.CreateScope())
{
var authService = scope.ServiceProvider.GetRequiredService();
_logger.LogInformation("Checking if token is invalidated.");
var isInvalidated = await authService.IsTokenInvalidatedAsync(token);
if (isInvalidated)
{
_logger.LogWarning("Token is invalidated.");
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Token has been invalidated.");
return;
}
}
_logger.LogInformation("Token is valid.");
await _next(context);
}
}
}
Код: Выделить всё
using System.Net;
using baio_api.Common.Middlewares;
using baio_api.Infrastructure.Services.Interfaces;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Moq;
namespace baio_api.tests.Unit.Common.Middlewares
{
public class TokenValidationMiddlewareTests
{
[Fact]
public async Task InvokeAsync_TokenIsInvalidated_ReturnsUnauthorized()
{
// Arrange
var authServiceMock = new Mock();
authServiceMock.Setup(s => s.IsTokenInvalidatedAsync(It.IsAny())).ReturnsAsync(true);
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddLogging(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Information);
});
services.AddSingleton(authServiceMock.Object);
services.AddScoped();
})
.Configure(app =>
{
app.UseMiddleware();
app.Run(async context =>
{
await context.Response.WriteAsync("Request passed through middleware.");
});
});
var server = new TestServer(builder);
var client = server.CreateClient();
// Act
var request = new HttpRequestMessage(HttpMethod.Get, "/");
request.Headers.Add("Authorization", "Bearer fake-token");
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
Assert.Equal("Token has been invalidated.", content);
}
[Fact]
public async Task InvokeAsync_TokenIsValid_ContinuesToNextMiddleware()
{
// Arrange
var authServiceMock = new Mock();
authServiceMock.Setup(s => s.IsTokenInvalidatedAsync(It.IsAny())).ReturnsAsync(false);
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddLogging(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Information);
});
services.AddSingleton(authServiceMock.Object);
services.AddScoped();
})
.Configure(app =>
{
app.UseMiddleware();
app.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status200OK;
await context.Response.WriteAsync("Request passed through middleware.");
});
});
var server = new TestServer(builder);
var client = server.CreateClient();
// Act
var request = new HttpRequestMessage(HttpMethod.Get, "/");
request.Headers.Add("Authorization", "Bearer fake-token");
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var content = await response.Content.ReadAsStringAsync();
Assert.Equal("Request passed through middleware.", content);
}
}
}
Failed baio_api.tests.Unit.Common.Middlewares.TokenValidationMiddlewareTests.InvokeAsync_TokenIsInvalidated_ReturnsUnauthorized [30 мс]
Сообщение об ошибке:
Ошибка Assert.Equal(): значения различаются
Ожидается: несанкционировано
Фактическое: ОК
Трассировка стека:
в baio_api.tests.Unit. Common.Middlewares.TokenValidationMiddlewareTests.InvokeAsync_TokenIsInvalidated_ReturnsUnauthorized() в /Users/oliwierbaran/Projects/baio/baio-api.tests/src/Unit/Common/MiddlewareTests/TokenValidationMiddlewareTests.cs:строка 53
--- Конец трассировки стека из предыдущего местоположения ---
Я пробовал много раз, но не получил никаких журналов в терминале или консоли отладки.
Возможно, мое промежуточное программное обеспечение просто написано неправильно.
Это вставляется в мое приложение в этот файл следующим образом:
Код: Выделить всё
using baio_api.Common.Middlewares;
public static class MiddlewareExtensions
{
public static void UseCustomMiddlewares(this IApplicationBuilder app)
{
app.UseMiddleware();
}
}
Код: Выделить всё
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.ConfigureAuthentication(builder.Configuration);
builder.Services.ConfigureSwagger();
builder.Services.ConfigureDbContext(builder.Configuration);
builder.Services.ConfigureCors();
builder.Services.ConfigureEmailSettings(builder.Configuration);
builder.Services.ConfigureCustomServices();
builder.Services.ConfigureMapper();
builder.Services.ConfigureMediatR();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
app.UseCors("DevCorsPolicy");
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseCustomMiddlewares();
app.MapControllers();
app.Run();
Спасибо за совет.
Подробнее здесь: https://stackoverflow.com/questions/787 ... e-were-bad
Мобильная версия