Добавил получение guid пользователя по фио через токен
Create and publish a Docker image / Publish image (push) Successful in 3m54s
Create and publish a Docker image / Publish image (push) Successful in 3m54s
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace SfeduSchedule.Auth;
|
||||
|
||||
public static class ApiKeyAuthenticationDefaults
|
||||
{
|
||||
public const string Scheme = "ApiKey";
|
||||
public const string HeaderName = "X-Api-Key";
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace SfeduSchedule.Auth;
|
||||
|
||||
public class ApiKeyAuthenticationHandler(
|
||||
IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder,
|
||||
IConfiguration configuration)
|
||||
: AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
|
||||
{
|
||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
// Ожидаем ключ из ENV
|
||||
var expectedKey = configuration["API_KEY"];
|
||||
if (string.IsNullOrEmpty(expectedKey))
|
||||
return Task.FromResult(AuthenticateResult.Fail("API key is not configured."));
|
||||
|
||||
// Ищем ключ в заголовке X-Api-Key (и опционально в query ?api_key=)
|
||||
string? providedKey = null;
|
||||
|
||||
if (Request.Headers.TryGetValue(ApiKeyAuthenticationDefaults.HeaderName, out var values))
|
||||
providedKey = values.FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrEmpty(providedKey) &&
|
||||
Request.Query.TryGetValue("api_key", out var qv))
|
||||
providedKey = qv.FirstOrDefault();
|
||||
|
||||
if (string.IsNullOrEmpty(providedKey))
|
||||
// Нет ключа — позволь другим схемам (если есть) продолжить; при [Authorize] будет 401
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
|
||||
if (!ConstantTimeEquals(providedKey!, expectedKey))
|
||||
return Task.FromResult(AuthenticateResult.Fail("Invalid API key."));
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.NameIdentifier, "api-key"),
|
||||
new Claim(ClaimTypes.Name, "api-key-user"),
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, ApiKeyAuthenticationDefaults.Scheme);
|
||||
var principal = new ClaimsPrincipal(identity);
|
||||
var ticket = new AuthenticationTicket(principal, ApiKeyAuthenticationDefaults.Scheme);
|
||||
|
||||
return Task.FromResult(AuthenticateResult.Success(ticket));
|
||||
}
|
||||
|
||||
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Response.Headers["WWW-Authenticate"] =
|
||||
$"{ApiKeyAuthenticationDefaults.Scheme} realm=\"api\", header=\"{ApiKeyAuthenticationDefaults.HeaderName}\"";
|
||||
Response.StatusCode = 401;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static bool ConstantTimeEquals(string a, string b)
|
||||
{
|
||||
var aBytes = Encoding.UTF8.GetBytes(a);
|
||||
var bBytes = Encoding.UTF8.GetBytes(b);
|
||||
|
||||
if (aBytes.Length != bBytes.Length)
|
||||
return false;
|
||||
|
||||
return CryptographicOperations.FixedTimeEquals(aBytes, bBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace SfeduSchedule.Auth
|
||||
{
|
||||
public class SwaggerAuthorizeOperationFilter : IOperationFilter
|
||||
{
|
||||
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||
{
|
||||
var hasAuthorize = context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
|
||||
context.MethodInfo.DeclaringType?.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() == true;
|
||||
if (hasAuthorize)
|
||||
{
|
||||
operation.Security ??= new List<OpenApiSecurityRequirement>();
|
||||
operation.Security.Add(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = ApiKeyAuthenticationDefaults.Scheme
|
||||
}
|
||||
},
|
||||
new List<string>()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user