Итак, я пытался настроить небольшой тестовый API с аутентификацией токена в форме JWT-дистрибутива, часть распространения токена работала как задумано.
Однако, поскольку я хотел создать методы для моегоСервис JWT более универсален, чтобы разрешать различные виды подписи токенов (так как я бы предпочел частную / открытую пару ключей), я попытался настроить некоторые дополнительные параметры в файлах appsettings, которые затем определяли бы способ генерации токенов,загрузка этих настроек началась с внедрения зависимостей, который я почти не исправлял до сих пор.
Итак, проблема возникла, когда я захотел взять те классы конфигурации, которые я установил, как одиночные (большинство руководств, которые япрочитайте до сих пор, что сделали это, так что я предполагаю, что это несколько правильно) и использую их в методе ConfigureServices, в который они добавили, чтобы я мог использовать параметры, которые, по моему мнению, должны были быть установлены, так как я настроил несколько строквыше, получив раздел appsettings file.
Однако, как только я пытаюсь получить к ним доступ, я ничего не получаю, и вместо этого у меня остаются пустые значения.
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//the token config takes values from the appsettings.json file
var tokenConf = Configuration.GetSection("TokenConfiguration");
services.Configure<TokenConfiguration>(tokenConf);
//the signing credentials are assigned in the JwtTokenService constructor
var signingConf = new SigningConfiguration();
services.AddSingleton<SigningConfiguration>(signingConf);
//my token service
services.AddSingleton<IJwtTokenService, JwtTokenService>();
//i try to get hold of the actual values to use later on
var provider = services.BuildServiceProvider();
TokenConfiguration tc = provider.GetService<TokenConfiguration>();
SigningConfiguration sc = provider.GetService<SigningConfiguration>();
//i wanna use the values in here when i set the parameters for my authentication
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
return Task.CompletedTask;
}
};
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
//values used here since i specify issuer, audience and what kind of key to use in the settings
//the key & credentials differ based on a bool in the settings file and will either be a symmetric or asymmetric key
ValidIssuer = tc.Issuer,
ValidAudience = tc.Audience,
IssuerSigningKey = sc.Key
};
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
JwtTokenService.cs (IJwtTokenService имеет только метод CreateToken, который реализован здесь)
public class JwtTokenService : IJwtTokenService
{
private TokenConfiguration tokenConf;
public SigningConfiguration signingConf;
public JwtTokenService(IOptions<TokenConfiguration> tc) {
tokenConf = tc.Value;
signingConf = new SigningConfiguration();
//if the asymmetric bool is set to true, assign a new rsa keypair to the signing configuration
//otherwise, use a symmetric key with a hmac hash
if (tc.Value.AsymmetricKey)
{
using (var provider = new RSACryptoServiceProvider(2048))
{
signingConf.Key = new RsaSecurityKey(provider.ExportParameters(true));
}
signingConf.SigningCredentials =
new SigningCredentials(
signingConf.Key,
SecurityAlgorithms.RsaSha256);
}
else {
signingConf.Key =
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(tc.Value.HmacSecret));
signingConf.SigningCredentials =
new SigningCredentials(
signingConf.Key,
SecurityAlgorithms.HmacSha512);
}
}
/// <summary>
/// Creates a token based on the running configuration
/// </summary>
public string CreateToken(List<Claim> claims)
{
var token = new JwtSecurityToken(
issuer: tokenConf.Issuer,
audience: tokenConf.Audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(tokenConf.Minutes),
signingCredentials: signingConf.SigningCredentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
TokenConfiguration.cs
public class TokenConfiguration
{
public string Audience { get; set; }
public string Issuer { get; set; }
public int Minutes { get; set; }
public bool AsymmetricKey { get; set; }
public string HmacSecret { get; set; }
}
SigningConfiguration.cs
public class SigningConfiguration
{
public SecurityKey Key { get; set; }
public SigningCredentials SigningCredentials { get; set; }
}
appsettings.json
"TokenConfiguration": {
"Audience": "ExampleAudience",
"Issuer": "ExampleIssuer",
"Minutes": 30,
"AsymmetricKey": true,
"HmacSecret": "example-secret-top-secret-secret-is_secret"
}
(проект работает в asp.net core 2.1 в случае, если это имеет значение)
Я новичок в DI и не могу найтиВо многих примерах сценарий использования такой же, как и у меня, и в большинстве таких случаев используются реальные службы, а не добавление класса «конфигурации» через DI.
Вероятно, есть способ получше, и яЯ, вероятно, просто глуп, что не заметил или не знал, что именно нужно Google, чтобы получить правильный ответ, и, скорее всего, будет наблюдать / читать о DI после этого, независимо от этого.
Любой ввод или мысли будутвысоко ценится,поскольку я все еще плохо знаком с ядром asp.net и всем этим.
В качестве небольшого побочного вопроса относительно генерации секретного ключа, в моем случае, было бы лучше сохранить сгенерированную пару ключей вхранилище ключей, или для хранения его в памяти, или наилучшим вариантом будет генерирование их через что-то вроде openSSL и чтение из них при запуске?