.NET Core:使用存储在数据库中的密钥设置 IssuerSigningKey 的最佳实践

问题描述 投票:0回答:1

我有一个 ASP.NET Core Web API 项目,其中初始化代码位于

Program.cs
中,我需要设置 JWT 身份验证,并且在那里我需要设置
IssuerSigningKey
,它是从 SQL 数据库获取的,因为我使用 .NET Core / EF
dataprotection
库自动生成和更新密钥。我面临的问题是我必须手动创建新的
DbContext
,而不是能够使用依赖注入,以下是我的代码,想知道这是否是实现我的目标的合法方法

var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseSqlServer(connectionString, x => x.UseNetTopologySuite())
    .Options;

OperationalStoreOptions storeOptions = new OperationalStoreOptions();

IOptions<OperationalStoreOptions> operationalStoreOptions = Options.Create(storeOptions);

var context = new ApplicationDbContext(contextOptions, operationalStoreOptions);

SymmetricSecurityKey securitykey = null;
var keyDb = context.DataProtectionKeys.FirstOrDefault();

if (keyDb == null || keyDb.Xml == null)
{
    throw new ArgumentException("security key missing!");
}
else
{
    XDocument keyDoc = XDocument.Parse(keyDb.Xml);
    string keyAsStr = keyDoc.Descendants("value").First().ToString();
    byte[] keyAsBytes = Encoding.UTF8.GetBytes(keyAsStr);
    securitykey = SymmetricSecurityKey(keyAsBytes);
}

builder.Services.AddAuthentication(options =>
{
   options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
   options.TokenValidationParameters = new TokenValidationParameters {
                                             ValidateIssuer = true,
                                             ValidateAudience = true,
                                             ValidateLifetime = true,
                                             ValidateIssuerSigningKey = true,
                                             ValidIssuer = "****",
                                             ValidAudience = "****",
                                             IssuerSigningKey = securitykey 
                                       };
        }); 
entity-framework .net-core
1个回答
0
投票

我不知道你的 ApplicationDbContext 对第二个参数做了什么,但我认为它可以通过一种简单的方式完成。我的想法是向您的模型添加一个新类和一个新接口:

public interface IMyService
{
    IOptions<OperationalStoreOptions> GetOptions();
}
public class MyService : IMyService
{        
    public IOptions<OperationalStoreOptions> GetOptions()
    {
        OperationalStoreOptions storeOptions = new OperationalStoreOptions();
        return Options.Create(storeOptions);            
    }
}

然后你可以在你的Startup.cs中添加DI:

services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString, x => x.UseNetTopologySuite()));
services.AddScoped<IMyService, MyService>();

最后,我们不要忘记在 ApplicationDbContext 构造函数中添加引用:

public class ApplicationDbContext : DbContext
{
    private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IMyService operationalStoreOptions) : base(options)
    {
        _operationalStoreOptions = operationalStoreOptions.GetOptions();
    }

    ....your code (DbSet,...)
}
© www.soinside.com 2019 - 2024. All rights reserved.