带AspNetIdentity和Registration API方法的IdentityServer4

时间:2018-08-02 13:57:45

标签: asp.net-core asp.net-identity identityserver4

我已经设置了IdentityServer4,一个受保护的API(核心)项目以及各种客户端。匿名访问的客户端页面使用资源所有者流来访问API,并且需要登录的客户端页面使用用户凭证。一切正常。我的问题是,现在我想添加受保护的注册API方法。

新的注册方法要求API项目使用AspNetIdentity。具体来说,他们使用Identity的UserManager对象无法实例化,除非我将此代码添加到Startup.ConfigureServices中。

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

但是添加此代码会破坏常规的IDServer4 Bearer身份验证。现在,API控制器上的Authorize标签将请求者发送到登录页面。有没有一种方法可以在没有上述代码的情况下创建好的userManager组件,从而使身份验证不起作用?

没有上面的代码,我得到以下错误:

Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[TestAPICore.Models.ApplicationUser]' while attempting to activate *controller*

这是我的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ApiName = "api1";
            });

        services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        }));

        //// ADDING THIS CAUSES API requests to send back the login screen
        //services.AddIdentity<ApplicationUser, IdentityRole>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>()
        //    .AddDefaultTokenProviders();

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

        services.AddMvc();
    }

这项工作的想法吗?

更新

要了解更多信息,似乎要调用services.AddIdentityCore<ApplicationUser>(cfg => {});。我在.AddAuthentication代码之前和之后都尝试过,但是仍然收到几乎相同的错误:

System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore`1[TestAPICore.Models.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager`1[TestAPICore.Models.ApplicationUser]'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites...

...这稍有不同,因为它不再引用我的控制器。

已解决!

这是起作用的...

IdentityBuilder builder = services.AddIdentityCore<ApplicationUser>(options => { });
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
builder.AddEntityFrameworkStores<ApplicationDbContext>();

谢谢,柯克,向我指出了正确的方向!

1 个答案:

答案 0 :(得分:2)

为了让其他人受益,这是我用于API项目的整个ConfigureServices方法,该方法可以管理用户,但仍可以通过IdentityServer进行身份验证:

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));


            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;

                    options.ApiName = "api1";
                });

            services.AddCors(o => o.AddPolicy("MyPolicy", bld =>
            {
                bld.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            }));

            // *** The Fix ***
            IdentityBuilder builder = services.AddIdentityCore<ApplicationUser>(options => { });
            builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
            builder.AddEntityFrameworkStores<ApplicationDbContext>();

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

            services.AddMvc();
        }