我有一个使用 EFCore 和一些现有实体的 .Net Core 7 应用程序。现在,其中的所有内容都已测试并正常工作,我想添加身份功能,然后将 AspNetUsers 链接到我现有的几个实体。
目前没有身份表,也没有身份功能使用的任何类型的表。
使用 Microsoft 教程 在没有现有授权的情况下将 Scaffold Identity 引入 Razor 项目 我进入了需要指定数据库和用户上下文的步骤。
在查找文档失败后,我输入了数据库上下文,作为我的数据项目中使用的数据库上下文(下面的“EventFinderData” - 与我的 Web 应用程序不同的项目,但在同一解决方案中)。然后我创建了一个新的用户上下文...
脚手架完成后,当脚手架过程创建新的数据上下文时,我收到许多不明确的引用错误:
// This is a duplicate class of that within the EventFinderData project, which is already referenced within my web app
public class EventFinderContext : IdentityDbContext<EventFinderWebAppRazorUser>
{
public EventFinderContext(DbContextOptions<EventFinderContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
我尝试创建两个类
partial
,但是当我添加迁移时,我得到:
发现多个 DbContext。指定使用哪一个。使用 PowerShell 命令的“-Context”参数和“--context” dotnet 命令的参数。
一些专家似乎建议开始一个已经包含身份的新项目,并从那里开始构建,但这将是一项艰巨的工作。
根据建议,以下是添加身份功能后我得到的三个类:
namespace EventFinderData
{
public class EventFinderContext : DbContext
{
public DbSet<EventItem> EventItems { get; set; }
public DbSet<EventCategory> EventCategories { get; set; }
public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options)
{
}
}
}
namespace EventFinderWebAppRazor.Data;
public class EventFinderWebAppRazorContext : IdentityDbContext<EventFinderWebAppRazorUser>
{
public EventFinderWebAppRazorContext(DbContextOptions<EventFinderWebAppRazorContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
namespace EventFinderWebAppRazor.Areas.Identity.Data;
public class EventFinderWebAppRazorUser : IdentityUser
{
}
builder.Services.AddDbContextFactory<EventFinderContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("EventFinderConnString"),
ss => ss.UseNetTopologySuite())
.EnableSensitiveDataLogging());
builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<EventFinderWebAppRazorContext>();
不确定是否发生了变化(此处为.net6),但要将 dot net 身份框架添加到现有上下文中,您所要做的就是在将其添加到 IServiceCollection 时提供该上下文。
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
})
.AddEntityFrameworkStores<ApplicationDbContext>()
您需要更改 DbContext,以便它继承自
IdentityDbContext<ApplicationUser>
这只会提供所需的服务,而不会提供构建它时出现的不同视图和用户体验流程。因此无需登录/注销、密码重置、MFA 设置等...
我希望这会有所帮助。
根据OP的更新,需要进行以下更新。
区域\身份\数据\EventFinderWebAppRazorUser.cs
将该类移至您的数据项目。它将成为您自己的实体模型的一部分。确保命名空间也已更新。虽然这并不是真正必要的,但是将所有实体都放在同一个命名空间中是很好的。
区域\身份\数据\EventFinderWebAppRazorContext.cs
删除该文件/类。这是脚手架过程创建的额外上下文,但由于我们想使用自己的上下文,所以不需要它。
EventFinderContext.cs
像下面一样更新这个类。
namespace EventFinderData
{
public class EventFinderContext : IdentityDbContext<EventFinderWebAppRazorUser>
{
public DbSet<EventItem> EventItems { get; set; }
public DbSet<EventCategory> EventCategories { get; set; }
public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options)
{
}
}
}
程序.cs
如下更新此文件。并确保通过更新 usings 来解决所有类型。
builder.Services.AddDbContextFactory<EventFinderContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("EventFinderConnString"),
ss => ss.UseNetTopologySuite())
.EnableSensitiveDataLogging());
builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<EventFinderData.EventFinderContext>();
builder.Services.AddIdentity<AppUser, IdentityRole>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequiredLength = 8;
opt.Password.RequireDigit = true;
opt.Password.RequireLowercase = true;
opt.Password.RequireUppercase = true;
opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(3);
opt.Lockout.MaxFailedAccessAttempts = 3;
opt.User.AllowedUserNameCharacters = default;
opt.User.RequireUniqueEmail = true;
}).AddEntityFrameworkStores<AppDbContext>().AddDefaultTokenProviders();
builder.Services.ConfigureApplicationCookie(con => { con.LoginPath = $"/Admin/Account/Login/{con.ReturnUrlParameter}"; });