我最近一直在研究.NET Core Web API。我刚刚使用JWT尝试进行身份验证,遵循https://stormpath.com/blog/token-authentication-asp-net-core上的指南。
一切顺利,直到我不得不用GetIdentity
方法用数据库查询替换硬编码的用户名和密码,并意识到我不知道如何从这个文件中访问数据库!
我所指的方法显示在第70行的下面链接中。 https://github.com/nbarbettini/SimpleTokenProvider/blob/master/test/SimpleTokenProvider.Test/Startup.Auth.cs
我的问题如下。
答案 0 :(得分:13)
是的,您可以访问数据库!在Configure
方法中运行的代码可以访问ConfigureServices
方法中添加的任何服务,包括数据库上下文等。
例如,如果您有一个简单的实体框架上下文:
using Microsoft.EntityFrameworkCore;
using SimpleTokenProvider.Test.Models;
namespace SimpleTokenProvider.Test
{
public class SimpleContext : DbContext
{
public SimpleContext(DbContextOptions<SimpleContext> options)
: base(options)
{
}
public DbSet<User> Users { get; set; }
}
}
然后将其添加到ConfigureServices
:
services.AddDbContext<SimpleContext>(opt => opt.UseInMemoryDatabase());
然后,您可以在设置中间件时访问它:
var context = app.ApplicationServices.GetService<SimpleContext>();
app.UseSimpleTokenProvider(new TokenProviderOptions
{
Path = "/api/token",
Audience = "ExampleAudience",
Issuer = "ExampleIssuer",
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
IdentityResolver = (username, password) => GetIdentity(context, username, password)
});
稍微改写GetIdentity
方法:
private Task<ClaimsIdentity> GetIdentity(SimpleContext context, string username, string password)
{
// Access the database using the context
// Here you'd need to do things like hash the password
// and do a lookup to see if the user + password hash exists
}
我是原始样本的作者。对不起,最初还不清楚!我尝试以一种易于提供自己的功能的方式编写IdentityResolver
委托 - 比如与您自己的数据库集成(如上所述),或者将其挂钩到ASP.NET Core Identity。当然,您可以随意丢弃我的代码并做更好的事情。 :)
答案 1 :(得分:6)
在.NET CORE 2.1上,只需将上下文作为参数传递给Configure方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, YourDbContext context)
{
//do whatever you want with the context here...
}
答案 2 :(得分:3)
接受的答案不适用于范围服务(如果您使用Entity Framework并使用AddDbContext
然后使用scoped添加上下文,则按请求创建this is the case服务)。
您可以在启动时按如下方式使用作用域服务(source):
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (var serviceScope = app.ApplicationServices.CreateScope())
{
var services = serviceScope.ServiceProvider;
var myDbContext = services.GetService<MyDbContext>();
}
}
或将其传递给Configure
方法的参数,如答案
juanora
答案 3 :(得分:0)
我可能在某些其他级别上错了,但我找到的解决方案是创建一个范围。
我在GetIdentity中传递了app而不是ctx,然后在使用范围的GetIdentity中传递:
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()) {
if (serviceScope.ServiceProvider.GetService<YourAppDbContext>() != null)
{
var ctx = serviceScope.ServiceProvider.GetService<YourAppDbContext>();
if (AnAuthenticateMethodHereMaybe(ctx, username, password)) {
return Task.FromResult(new ClaimsIdentity(new
GenericIdentity(username, "Token"), new Claim[] { }));
}
}
}