ASP.NET MVC 框架中的身份使用 Identity Core
Identity in ASP.NET MVC Framework using Identity Core
我在部分切换到 .NET Standard 时遇到问题。
我正在将 class 库迁移到 .NET Standard,在这个库中我有存储库和数据库通信。我已经成功迁移它以使用 AspNetCore.Identity.EntityFrameworkCore
。我试图实现的目标是最终让 1 个 .NET Standard 项目负责数据库,其中 1 个 MVC .NET Framework、1 API .NET Framework 和 1 个新的 .NET Core 应用程序将使用它。除此之外,其他一些 .NET Framework class 库也依赖于它。基本上 .NET Core 应用程序已经制作完成,但后端尚未 'merged' 重叠功能。
小概览:
不将 MVC/API 转换为 .Core 的原因是目前有太多其他库依赖于 .NET Framework,有些还不能转换,但是对数据库使用相同的库是一个根本性的变化,它将避免某些存储库的双重实现。
我也已经转换了实现 Microsoft.AspNetCore.Identity.IdentityUser
、Microsoft.AspNetCore.Identity.IdentityRole
等的实体。
所以我的 DbContext class 看起来像这样:
public class DatabaseContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken>
{
private IConfiguration _config;
public DatabaseContext(IConfiguration config) : base()
{
_config = config;
}
//all DbSet, OnModelCreating
}
我已成功 运行 EFCore 代码首次迁移。
现在我正在尝试在我的 MVC 应用程序中配置标识(然后也在 API 项目中)。
我只有标准 IdentityConfig.cs
、Startup.Auth.cs
,所有配置都已完成。我试过查看此文档 (migration identity)。我所能做的就是添加这个,其中 AddMvc()
不存在,因此会引发编译错误:
Startup.cs
using System;
using System.IO;
using Babywatcher.Core.Data.Database;
using Babywatcher.Core.Data.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(MyProject.MVC.Startup))]
namespace MyProject.MVC
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var services = new ServiceCollection();
ConfigureAuth(app);
ConfigureServices(services);
}
public void ConfigureServices(IServiceCollection services)
{
// Add EF services to the services container.
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(""));//Configuration trying to refer to above method: Configuration.GetConnectionString("DefaultConnection")
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();
services.AddMvc();
}
}
}
好吧,我想这并没有多大作用,而且我在两个 .NET Framework 项目中都使用了 SimpleInjector,我希望尽可能继续使用它,而不是使用默认的依赖项注入器。
通过上面的添加,我真的不知道如何使用 ConfigureAuth
方法以及将所有配置放在哪里。
当我尝试调整 IdentityManager 以尝试引用 AspNetCore.Identity
中的相同类型时,我在尝试更改 ApplicationUserManager
:
时开始遇到问题
创建 UserStore 不是问题,但是尝试创建 UserManager
比较困难,我也试过在我的 UserRepository
中使用它,就像我以前做的那样,我可以现在不用了:(.
旧用户存储库
private readonly UserManager<ApplicationUser, string> _userManager = null;
private readonly RoleManager<ApplicationRole, string> _roleManager = null;
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public UserRepository(DatabaseContext dbContext) : base(dbContext, c => c.contactId, m => m.ContactId)
{
var userStore =
new UserStore<ApplicationUser, ApplicationRole, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(dbContext);
var roleStore = new RoleStore<ApplicationRole, string, ApplicationUserRole>(dbContext);
_userManager = new UserManager<ApplicationUser, string>(userStore);
_roleManager = new RoleManager<ApplicationRole, string>(roleStore);
_userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager) { AllowOnlyAlphanumericUserNames = false };
if (DataProtectionProvider == null)
{
DataProtectionProvider = new MachineKeyProtectionProvider();
}
_userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, string>(DataProtectionProvider.Create("Identity"));
}
尝试再次执行上述操作会在创建 UserManager
时出现问题,因为它要求 9 个参数,所以我有点觉得不应该这样做......可能会做 让他们到达那里当然我首先要解决根本问题。
最后但同样重要的是:请记住,这些应用程序都已投入生产,因此特别是在用户周围,我需要确保所有登录仍然有效。启用此版本时,由于其他一些迁移问题,我需要将数据迁移到新数据库。
好吧,这是一个很长的答案,准备好第二天花在你的头发上吧:)。
首先是 IApplicationUser
的一个接口,由 2 个不同的 类:
实现
public interface IApplicationUser
{
string Id { get; set; }
/// <summary>Gets or sets the user name for this user.</summary>
string UserName { get; set; }
}
实施 1,这是我的数据库实体的一部分:
public class ApplicationUser : IdentityUser<string>, IApplicationUser
{
public DateTime? LockoutEndDateUtc { get; set; }
public bool RequiresPasswordCreation { get; set; }
public string TemporaryToken { get; set; }
}
实施 2,对于我的 .NET Framework 项目:
public class ApplicationUserMvc : IdentityUser<string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IApplicationUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUserMvc, string> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
...all the other things
}
然后我创建了自己的身份管理器(界面)
public interface IIdentityManager
{
//User manager methods
Task<IIdentityResult> CreateAsync(IApplicationUser user);
//..all methods needed
}
public interface IIdentityResult
{
bool Succeeded { get; set; }
List<string> Errors { get; set; }
}
然后是我的实际实现,所以这是我的 .NET Core 项目。
public class IdentityManagerCore : IIdentityManager
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
public IdentityManagerCore(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
public async Task<IIdentityResult> CreateAsync(IApplicationUser user)
{
ApplicationUser realUser = new ApplicationUser()
{
Id = user.Id,
TemporaryToken = user.TemporaryToken,
AccessFailedCount = user.AccessFailedCount,
ConcurrencyStamp = user.ConcurrencyStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
LockoutEnabled = user.LockoutEnabled,
LockoutEnd = user.LockoutEnd,
NormalizedEmail = user.NormalizedEmail,
NormalizedUserName = user.NormalizedUserName,
PasswordHash = user.PasswordHash,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
RequiresPasswordCreation = user.RequiresPasswordCreation,
SecurityStamp = user.SecurityStamp,
TwoFactorEnabled = user.TwoFactorEnabled,
UserName = user.UserName
};
var result = await _userManager.CreateAsync(realUser);
return ConvertToInterface(result);
}
private IIdentityResult ConvertToInterface(IdentityResult result)
{
IIdentityResult realResult = new IdentityResultCore();
realResult.Succeeded = result.Succeeded;
realResult.Errors = result.Errors?.Select(x => x.Description).ToList();
return realResult;
}
}
public class IdentityResultCore : IdentityResult, IIdentityResult
{
private IEnumerable<string> _errors;
private bool _succeed;
public new bool Succeeded
{
get => base.Succeeded || _succeed;
set => _succeed = value;
}
public new List<string> Errors
{
get => base.Errors?.Select(x => x.Description).ToList() ?? _errors?.ToList();
set => _errors = value;
}
}
UserManager
和 RoleManager
在启动时注入,如下所示:
services.AddTransient<IIdentityManager, IdentityManagerCore>();
.NET Framework 实现:
public class IdentityManagerMvc : IIdentityManager
{
private readonly UserManager<ApplicationUserMvc, string> _userManager = null;
private readonly RoleManager<ApplicationRoleMvc, string> _roleManager = null;
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public IdentityManagerMvc(DatabaseContextMvc dbContext)
{
var userStore =
new UserStore<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(dbContext);
var roleStore = new RoleStore<ApplicationRoleMvc, string, ApplicationUserRole>(dbContext);
_userManager = new UserManager<ApplicationUserMvc, string>(userStore);
_roleManager = new RoleManager<ApplicationRoleMvc, string>(roleStore);
_userManager.UserValidator = new UserValidator<ApplicationUserMvc>(_userManager) { AllowOnlyAlphanumericUserNames = false };
if (DataProtectionProvider == null)
{
DataProtectionProvider = new MachineKeyProtectionProvider();
}
_userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUserMvc, string>(DataProtectionProvider.Create("Identity"));
}
public async Task<IIdentityResult> CreateAsync(IApplicationUser user)
{
ApplicationUserMvc realUser = new ApplicationUserMvc()
{
Id = user.Id,
TemporaryToken = user.TemporaryToken,
AccessFailedCount = user.AccessFailedCount,
ConcurrencyStamp = user.ConcurrencyStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
LockoutEnabled = user.LockoutEnabled,
LockoutEnd = user.LockoutEnd,
NormalizedEmail = user.NormalizedEmail,
NormalizedUserName = user.NormalizedUserName,
PasswordHash = user.PasswordHash,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
RequiresPasswordCreation = user.RequiresPasswordCreation,
SecurityStamp = user.SecurityStamp,
TwoFactorEnabled = user.TwoFactorEnabled,
UserName = user.UserName
};
var result = await _userManager.CreateAsync(realUser);
return ConvertToInterface(result);
}
private IIdentityResult ConvertToInterface(IdentityResult result)
{
IIdentityResult realResult = new IdentityResultMvc();
realResult.Succeeded = result.Succeeded;
realResult.Errors = result.Errors?.ToList();
return realResult;
}
}
public class IdentityResultMvc : IdentityResult, IIdentityResult
{
private IEnumerable<string> _errors;
private bool _succeed;
public new bool Succeeded
{
get => base.Succeeded || _succeed;
set => _succeed = value;
}
public new List<string> Errors
{
get => base.Errors?.ToList() ?? _errors?.ToList();
set => _errors = value;
}
}
最后但同样重要的是,您的 .NET Framework 项目需要一个单独的 DatabaseContext
,这个项目将仅用于 "identity" 目的,因此不会实际查询任何数据,仅用于认证,授权。
public class DatabaseContextMvc : IdentityDbContext<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin,
ApplicationUserRole, ApplicationUserClaim>
{
public DatabaseContextMvc() : base("DatabaseContext")
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
//Database.SetInitializer<DatabaseContextMvc>(null);
}
public void SetTimeout(int minutes)
{
this.Database.CommandTimeout = minutes * 60;
}
public static DatabaseContextMvc Create()
{
return new DatabaseContextMvc();
}
}
此时您应该具备在任何地方使用它所必需的所有 类。
因此,例如,在您的 .NET Framework 项目中,您可以像这样设置 ApplicationUserManager
:
public class ApplicationUserManager : UserManager<ApplicationUserMvc, string>
{
public ApplicationUserManager(IUserStore<ApplicationUserMvc, string> store)
: base(store)
{//look at where i used applicationUserMvc
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var userStore =
new UserStore<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(context.Get<DatabaseContextMvc>());
//ApplicationUserLogin,UserRole,UserClaim are self created but just override IdentityUserLogin (for example).
var manager = new ApplicationUserManager(userStore);
}
...
}
无论您在 .NET Framework 中使用什么依赖注入,请确保注册您的 DatabaseContext
和 DatabaseContextMvc
。
这是我的 DatabaseContext
,它位于 .NET Standard 库中并在 .NET Core 和 .NET Framework 中使用:
public class DatabaseContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken>
{
private IConfiguration _config;
public string ConnectionString { get; }
public DatabaseContext(IConfiguration config) : base()
{
_config = config;
var connectionString = config.GetConnectionString("DatabaseContext");
ConnectionString = connectionString;
}
public void SetTimeout(int minutes)
{
Database.SetCommandTimeout(minutes * 60);
}
public virtual DbSet<Address> Addresses { get; set; }
public static DatabaseContext Create(IConfiguration config)
{
return new DatabaseContext(config);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//setup code for the DbContextOptions
optionsBuilder
.UseSqlServer(ConnectionString,
providerOptions => providerOptions.CommandTimeout(60))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
base.OnConfiguring(optionsBuilder);
}
经过这么长时间 post 或实施之后,您的注意力可能已经消失了,但再多说几句:
- 我敢保证,有了这个你一定会用得上,这半年来一直用得很好。
- 所以 .NET Standard(以及 EntityFrameworkCore)是进行数据库操作的主要方式,大部分代码都是为了应对 .NET Framework。
- 您将努力安装正确的依赖项。它会导致运行时异常,你会很快遇到但很容易解决,.NET Framework 只需要为自己安装依赖项。确保版本一致,使用 Manage NuGet packages for Solution 下的 Consolidate 版本(右键单击解决方案)。
您必须以网络核心的方式进行设置:因此您的 .NET Framework 项目中也需要 appsettings.json。另外在Web.Config中还是需要的,这主要是为了认证的一小部分。
private IConfiguration GetConfiguartion()
{
var path = Server.MapPath("~/");
var builder = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile("appsettings.json");
return builder.Build();//inject the return IConfiguration in your DI
}
祝你好运。如果您认为这很困难并且会造成很多麻烦:正确,如果您有一个小型应用程序,您最好将所有内容都转换为 .NET Core / .NET Standard。
我在部分切换到 .NET Standard 时遇到问题。
我正在将 class 库迁移到 .NET Standard,在这个库中我有存储库和数据库通信。我已经成功迁移它以使用 AspNetCore.Identity.EntityFrameworkCore
。我试图实现的目标是最终让 1 个 .NET Standard 项目负责数据库,其中 1 个 MVC .NET Framework、1 API .NET Framework 和 1 个新的 .NET Core 应用程序将使用它。除此之外,其他一些 .NET Framework class 库也依赖于它。基本上 .NET Core 应用程序已经制作完成,但后端尚未 'merged' 重叠功能。
小概览:
不将 MVC/API 转换为 .Core 的原因是目前有太多其他库依赖于 .NET Framework,有些还不能转换,但是对数据库使用相同的库是一个根本性的变化,它将避免某些存储库的双重实现。
我也已经转换了实现 Microsoft.AspNetCore.Identity.IdentityUser
、Microsoft.AspNetCore.Identity.IdentityRole
等的实体。
所以我的 DbContext class 看起来像这样:
public class DatabaseContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken>
{
private IConfiguration _config;
public DatabaseContext(IConfiguration config) : base()
{
_config = config;
}
//all DbSet, OnModelCreating
}
我已成功 运行 EFCore 代码首次迁移。
现在我正在尝试在我的 MVC 应用程序中配置标识(然后也在 API 项目中)。
我只有标准 IdentityConfig.cs
、Startup.Auth.cs
,所有配置都已完成。我试过查看此文档 (migration identity)。我所能做的就是添加这个,其中 AddMvc()
不存在,因此会引发编译错误:
Startup.cs
using System;
using System.IO;
using Babywatcher.Core.Data.Database;
using Babywatcher.Core.Data.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(MyProject.MVC.Startup))]
namespace MyProject.MVC
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var services = new ServiceCollection();
ConfigureAuth(app);
ConfigureServices(services);
}
public void ConfigureServices(IServiceCollection services)
{
// Add EF services to the services container.
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(""));//Configuration trying to refer to above method: Configuration.GetConnectionString("DefaultConnection")
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();
services.AddMvc();
}
}
}
好吧,我想这并没有多大作用,而且我在两个 .NET Framework 项目中都使用了 SimpleInjector,我希望尽可能继续使用它,而不是使用默认的依赖项注入器。
通过上面的添加,我真的不知道如何使用 ConfigureAuth
方法以及将所有配置放在哪里。
当我尝试调整 IdentityManager 以尝试引用 AspNetCore.Identity
中的相同类型时,我在尝试更改 ApplicationUserManager
:
创建 UserStore 不是问题,但是尝试创建 UserManager
比较困难,我也试过在我的 UserRepository
中使用它,就像我以前做的那样,我可以现在不用了:(.
旧用户存储库
private readonly UserManager<ApplicationUser, string> _userManager = null;
private readonly RoleManager<ApplicationRole, string> _roleManager = null;
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public UserRepository(DatabaseContext dbContext) : base(dbContext, c => c.contactId, m => m.ContactId)
{
var userStore =
new UserStore<ApplicationUser, ApplicationRole, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(dbContext);
var roleStore = new RoleStore<ApplicationRole, string, ApplicationUserRole>(dbContext);
_userManager = new UserManager<ApplicationUser, string>(userStore);
_roleManager = new RoleManager<ApplicationRole, string>(roleStore);
_userManager.UserValidator = new UserValidator<ApplicationUser>(_userManager) { AllowOnlyAlphanumericUserNames = false };
if (DataProtectionProvider == null)
{
DataProtectionProvider = new MachineKeyProtectionProvider();
}
_userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, string>(DataProtectionProvider.Create("Identity"));
}
尝试再次执行上述操作会在创建 UserManager
时出现问题,因为它要求 9 个参数,所以我有点觉得不应该这样做......可能会做
最后但同样重要的是:请记住,这些应用程序都已投入生产,因此特别是在用户周围,我需要确保所有登录仍然有效。启用此版本时,由于其他一些迁移问题,我需要将数据迁移到新数据库。
好吧,这是一个很长的答案,准备好第二天花在你的头发上吧:)。
首先是 IApplicationUser
的一个接口,由 2 个不同的 类:
public interface IApplicationUser
{
string Id { get; set; }
/// <summary>Gets or sets the user name for this user.</summary>
string UserName { get; set; }
}
实施 1,这是我的数据库实体的一部分:
public class ApplicationUser : IdentityUser<string>, IApplicationUser
{
public DateTime? LockoutEndDateUtc { get; set; }
public bool RequiresPasswordCreation { get; set; }
public string TemporaryToken { get; set; }
}
实施 2,对于我的 .NET Framework 项目:
public class ApplicationUserMvc : IdentityUser<string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IApplicationUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUserMvc, string> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
...all the other things
}
然后我创建了自己的身份管理器(界面)
public interface IIdentityManager
{
//User manager methods
Task<IIdentityResult> CreateAsync(IApplicationUser user);
//..all methods needed
}
public interface IIdentityResult
{
bool Succeeded { get; set; }
List<string> Errors { get; set; }
}
然后是我的实际实现,所以这是我的 .NET Core 项目。
public class IdentityManagerCore : IIdentityManager
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
public IdentityManagerCore(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
public async Task<IIdentityResult> CreateAsync(IApplicationUser user)
{
ApplicationUser realUser = new ApplicationUser()
{
Id = user.Id,
TemporaryToken = user.TemporaryToken,
AccessFailedCount = user.AccessFailedCount,
ConcurrencyStamp = user.ConcurrencyStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
LockoutEnabled = user.LockoutEnabled,
LockoutEnd = user.LockoutEnd,
NormalizedEmail = user.NormalizedEmail,
NormalizedUserName = user.NormalizedUserName,
PasswordHash = user.PasswordHash,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
RequiresPasswordCreation = user.RequiresPasswordCreation,
SecurityStamp = user.SecurityStamp,
TwoFactorEnabled = user.TwoFactorEnabled,
UserName = user.UserName
};
var result = await _userManager.CreateAsync(realUser);
return ConvertToInterface(result);
}
private IIdentityResult ConvertToInterface(IdentityResult result)
{
IIdentityResult realResult = new IdentityResultCore();
realResult.Succeeded = result.Succeeded;
realResult.Errors = result.Errors?.Select(x => x.Description).ToList();
return realResult;
}
}
public class IdentityResultCore : IdentityResult, IIdentityResult
{
private IEnumerable<string> _errors;
private bool _succeed;
public new bool Succeeded
{
get => base.Succeeded || _succeed;
set => _succeed = value;
}
public new List<string> Errors
{
get => base.Errors?.Select(x => x.Description).ToList() ?? _errors?.ToList();
set => _errors = value;
}
}
UserManager
和 RoleManager
在启动时注入,如下所示:
services.AddTransient<IIdentityManager, IdentityManagerCore>();
.NET Framework 实现:
public class IdentityManagerMvc : IIdentityManager
{
private readonly UserManager<ApplicationUserMvc, string> _userManager = null;
private readonly RoleManager<ApplicationRoleMvc, string> _roleManager = null;
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public IdentityManagerMvc(DatabaseContextMvc dbContext)
{
var userStore =
new UserStore<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(dbContext);
var roleStore = new RoleStore<ApplicationRoleMvc, string, ApplicationUserRole>(dbContext);
_userManager = new UserManager<ApplicationUserMvc, string>(userStore);
_roleManager = new RoleManager<ApplicationRoleMvc, string>(roleStore);
_userManager.UserValidator = new UserValidator<ApplicationUserMvc>(_userManager) { AllowOnlyAlphanumericUserNames = false };
if (DataProtectionProvider == null)
{
DataProtectionProvider = new MachineKeyProtectionProvider();
}
_userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUserMvc, string>(DataProtectionProvider.Create("Identity"));
}
public async Task<IIdentityResult> CreateAsync(IApplicationUser user)
{
ApplicationUserMvc realUser = new ApplicationUserMvc()
{
Id = user.Id,
TemporaryToken = user.TemporaryToken,
AccessFailedCount = user.AccessFailedCount,
ConcurrencyStamp = user.ConcurrencyStamp,
Email = user.Email,
EmailConfirmed = user.EmailConfirmed,
LockoutEnabled = user.LockoutEnabled,
LockoutEnd = user.LockoutEnd,
NormalizedEmail = user.NormalizedEmail,
NormalizedUserName = user.NormalizedUserName,
PasswordHash = user.PasswordHash,
PhoneNumber = user.PhoneNumber,
PhoneNumberConfirmed = user.PhoneNumberConfirmed,
RequiresPasswordCreation = user.RequiresPasswordCreation,
SecurityStamp = user.SecurityStamp,
TwoFactorEnabled = user.TwoFactorEnabled,
UserName = user.UserName
};
var result = await _userManager.CreateAsync(realUser);
return ConvertToInterface(result);
}
private IIdentityResult ConvertToInterface(IdentityResult result)
{
IIdentityResult realResult = new IdentityResultMvc();
realResult.Succeeded = result.Succeeded;
realResult.Errors = result.Errors?.ToList();
return realResult;
}
}
public class IdentityResultMvc : IdentityResult, IIdentityResult
{
private IEnumerable<string> _errors;
private bool _succeed;
public new bool Succeeded
{
get => base.Succeeded || _succeed;
set => _succeed = value;
}
public new List<string> Errors
{
get => base.Errors?.ToList() ?? _errors?.ToList();
set => _errors = value;
}
}
最后但同样重要的是,您的 .NET Framework 项目需要一个单独的 DatabaseContext
,这个项目将仅用于 "identity" 目的,因此不会实际查询任何数据,仅用于认证,授权。
public class DatabaseContextMvc : IdentityDbContext<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin,
ApplicationUserRole, ApplicationUserClaim>
{
public DatabaseContextMvc() : base("DatabaseContext")
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
//Database.SetInitializer<DatabaseContextMvc>(null);
}
public void SetTimeout(int minutes)
{
this.Database.CommandTimeout = minutes * 60;
}
public static DatabaseContextMvc Create()
{
return new DatabaseContextMvc();
}
}
此时您应该具备在任何地方使用它所必需的所有 类。
因此,例如,在您的 .NET Framework 项目中,您可以像这样设置 ApplicationUserManager
:
public class ApplicationUserManager : UserManager<ApplicationUserMvc, string>
{
public ApplicationUserManager(IUserStore<ApplicationUserMvc, string> store)
: base(store)
{//look at where i used applicationUserMvc
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var userStore =
new UserStore<ApplicationUserMvc, ApplicationRoleMvc, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(context.Get<DatabaseContextMvc>());
//ApplicationUserLogin,UserRole,UserClaim are self created but just override IdentityUserLogin (for example).
var manager = new ApplicationUserManager(userStore);
}
...
}
无论您在 .NET Framework 中使用什么依赖注入,请确保注册您的 DatabaseContext
和 DatabaseContextMvc
。
这是我的 DatabaseContext
,它位于 .NET Standard 库中并在 .NET Core 和 .NET Framework 中使用:
public class DatabaseContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken>
{
private IConfiguration _config;
public string ConnectionString { get; }
public DatabaseContext(IConfiguration config) : base()
{
_config = config;
var connectionString = config.GetConnectionString("DatabaseContext");
ConnectionString = connectionString;
}
public void SetTimeout(int minutes)
{
Database.SetCommandTimeout(minutes * 60);
}
public virtual DbSet<Address> Addresses { get; set; }
public static DatabaseContext Create(IConfiguration config)
{
return new DatabaseContext(config);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//setup code for the DbContextOptions
optionsBuilder
.UseSqlServer(ConnectionString,
providerOptions => providerOptions.CommandTimeout(60))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
base.OnConfiguring(optionsBuilder);
}
经过这么长时间 post 或实施之后,您的注意力可能已经消失了,但再多说几句:
- 我敢保证,有了这个你一定会用得上,这半年来一直用得很好。
- 所以 .NET Standard(以及 EntityFrameworkCore)是进行数据库操作的主要方式,大部分代码都是为了应对 .NET Framework。
- 您将努力安装正确的依赖项。它会导致运行时异常,你会很快遇到但很容易解决,.NET Framework 只需要为自己安装依赖项。确保版本一致,使用 Manage NuGet packages for Solution 下的 Consolidate 版本(右键单击解决方案)。
您必须以网络核心的方式进行设置:因此您的 .NET Framework 项目中也需要 appsettings.json。另外在Web.Config中还是需要的,这主要是为了认证的一小部分。
private IConfiguration GetConfiguartion() { var path = Server.MapPath("~/"); var builder = new ConfigurationBuilder() .SetBasePath(path) .AddJsonFile("appsettings.json"); return builder.Build();//inject the return IConfiguration in your DI }
祝你好运。如果您认为这很困难并且会造成很多麻烦:正确,如果您有一个小型应用程序,您最好将所有内容都转换为 .NET Core / .NET Standard。