【问题标题】:Using ASP.NET Identity in an ASP.NET Core MVC application without Entity Framework and Migrations在没有实体框架和迁移的 ASP.NET Core MVC 应用程序中使用 ASP.NET 标识
【发布时间】:2017-11-26 05:05:50
【问题描述】:

是否可以在没有实体框架和实体框架迁移的情况下使用 ASP.NET 标识?我的应用程序的其余部分将使用 Micro ORM 进行数据访问。但是,该应用程序使用的是内置的 ASP.NET Identity 个人用户帐户。

我的目标是仍然能够使用内置的 UserManager 和 LoginManager 类,并另外使用 Micro ORM 检索用户列表,并取消与 EF/Migrations 相关的任何事情。这可能吗?看起来不像,因为原始数据库结构是通过应用初始迁移创建的。

如果有人对此有很好的技术,请分享。

【问题讨论】:

  • @johnny5 所以看起来不值得。我想我只会使用 ApplicationDbContext 和 Migrations 保留 AspNetIdentity 的东西,而其他一切都使用 Micro ORM。这有意义吗?
  • 我一直在托管一个令牌服务器并一直在进行身份验证,尽管您可以查看 Identity Server 4,这可能有点矫枉过正,但它抽象了登录过程
  • @johnny5 我正在使用带 ASP.NET 身份的 IdentityServer4。 github.com/IdentityServer/IdentityServer4.Samples/tree/release/…。该项目使用 EF 和 Migrations...没有它我该怎么办?
  • 将 Identity Server 4 与 EF 结合使用,因为它是自包含的服务。您的其余服务使用其他 orm,但此项目将使用 EF
  • @johnny5 我有一个数据类库,它对所有的数据调用都使用了微结构。 Identity Server 对 AspNetUser 表使用 EF 和迁移。无论如何我可以清理这个吗?我明白了,我相信您所说的是认为 IdentityServer 正在使用 EF / Migrations 但我的应用程序的其余部分不正确?

标签: c# asp.net entity-framework asp.net-core asp.net-identity


【解决方案1】:

Asp.Net Identity 已经抽象出它需要的商店,他们商店的文档在这里;
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-custom-storage-providers

这是一个商店的例子;

public class InMemoryUserStore<TUser> :
        IUserStore<TUser>,
        IUserLoginStore<TUser>,
        IUserClaimStore<TUser>,
        IUserPasswordStore<TUser>,
        IUserSecurityStampStore<TUser>,
        IUserTwoFactorStore<TUser>,
        IUserEmailStore<TUser>,
        IUserLockoutStore<TUser>,
        IUserAuthenticatorKeyStore<TUser>,
        IUserTwoFactorRecoveryCodeStore<TUser>,
        IUserPhoneNumberStore<TUser> where TUser: MemoryIdentityUser
    {
        ...
    }

您也可以拥有自己的 User 对象,它不必从任何东西继承。

public class MemoryIdentityUser
{
    private List<MemoryUserClaim> _claims;
    private List<MemoryUserLogin> _logins;
    private List<MemoryUserToken> _tokens;
    ...
}

Asp.Net Identity 是一个引擎,因此是固执己见的。正是这种观点推动了商店的抽象化。我希望 Asp.Net Identity 文档有关于它如何与商店交互的完整序列图。至少有一些必须遵守的参考序列。

存储有一些怪癖,它需要一些方法,这些方法仅在实现中改变私有数据,然后是更新调用,假设您将把数据提交到持久存储。

你可能想看看这个项目; https://github.com/ghstahl/AspNetCore.2.InMemoryIdentity

您可以在没有数据库负担的情况下查看您需要做什么。

连接起来;

// My user is custom, so I made ApplicationUser inherit
public class ApplicationUser : MemoryIdentityUser
{
}

Startup.cs;

public void ConfigureServices(IServiceCollection services)
{
  services.AddSingleton<IUserStore<ApplicationUser>>(provider =>
  {
    return new InMemoryUserStore<ApplicationUser>();
  });
  services.AddIdentity<ApplicationUser>(Configuration)
          .AddDefaultTokenProviders();

  // Add application services.
  services.AddTransient<IEmailSender, EmailSender>();

  services.AddMvc();
}

在 AddIdentity 中,以下说明了您可以引入自己的实现的程度

public static class InMemoryIdentityServiceCollectionExtensions
{
    public static IdentityBuilder AddIdentity<TUser>(this IServiceCollection services, IConfiguration configuration)
        where TUser : class => services.AddIdentity<TUser>(configuration,null);

    public static IdentityBuilder AddIdentity<TUser>(this IServiceCollection services, IConfiguration configuration,Action<IdentityOptions> setupAction)
        where TUser : class
    {
        // Services used by identity
        var authenticationBuilder = services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
                options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
                options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
            })
            .AddCookie(IdentityConstants.ApplicationScheme, o =>
            {
                o.LoginPath = new PathString("/Account/Login");
                o.Events = new CookieAuthenticationEvents
                {
                    OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
                };
            })
            .AddCookie(IdentityConstants.ExternalScheme, o =>
            {
                o.Cookie.Name = IdentityConstants.ExternalScheme;
                o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
            })
            .AddCookie(IdentityConstants.TwoFactorRememberMeScheme,
                o => o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme)
            .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
            {
                o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
                o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
            });

        // Hosting doesn't add IHttpContextAccessor by default
        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        // Identity services
        services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
        services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
        services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
        services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();

        // No interface for the error describer so we can add errors without rev'ing the interface
        services.TryAddScoped<IdentityErrorDescriber>();
        services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
        services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser>>();
        services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
        services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();

        if (setupAction != null)
        {
            services.Configure(setupAction);
        }

        return new IdentityBuilder(typeof(TUser), services);
    }
}

有一堆 IUserStore 实现,每种类型的支持数据库。我从另一个使用 MongoDB 作为后备数据库的项目中复制了我的 InMemoryUserStore。

【讨论】:

  • 不鼓励仅链接的答案。您能否进一步充实您的答案,举例说明如何使用您链接的内容,或者更深入地解释一下?
【解决方案2】:

首先你需要创建一个自定义用户商店:

public class UserStore : IUserStore<IdentityUser>,
                         IUserClaimStore<IdentityUser>,
                         IUserLoginStore<IdentityUser>,
                         IUserRoleStore<IdentityUser>,
                         IUserPasswordStore<IdentityUser>,
                         IUserSecurityStampStore<IdentityUser>
{
    // interface implementations not shown
}

然后你需要将它注册到依赖注入容器中:

// Add identity types
services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddDefaultTokenProviders();

// Identity Services
services.AddTransient<IUserStore<ApplicationUser>, CustomUserStore>();
services.AddTransient<IRoleStore<ApplicationRole>, CustomRoleStore>();

这是documented here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多