繁体   English   中英

同一主机上的IdentityServer4 + API

[英]IdentityServer4 + API on same host

所以我有一个项目正在研究。

它用于登录和API。

我正在使用Identity Server 4,ASP.NET Core身份,MongoDB和OpenAPI。

Identity Server 4使用ASP.NET Core Identity,该身份通过MongoDB作为数据库提供程序实现。

我也有使用OpenAPI记录的API。 API和IDS4在同一主机上。

我面临以下问题:当我在Web界面中登录时(默认为Identity),方法SignInManager.IsSignedIn(User)返回false。

我的猜测是,我在身份验证级别上缺少/误解了一些(事实是Identity使用Cookies,但出于保护API的考虑,它是令牌。

我的Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        // Add the temp data provider
        services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

        // Add Identity with MongoDB
        services.AddIdentityMongoDbProvider<User>(options =>
        {
            options.ConnectionString = Configuration.GetValue<string>("Database:ConnectionString");
            options.DbType = Configuration.GetValue<DbType>("Database:DbType");
        });

        // Add EmailSender
        services.AddTransient<IEmailSender, EmailSender>();
        services.Configure<EmailSenderOptions>(Configuration.GetSection("MailSender"));

        // Add applications settings
        services.Configure<ApplicationOptions>(Configuration.GetSection("ApplicationOptions"));

        // Add IdentityServerClients configuration
        services.Configure<IdentityServerClientOptions>("EchinoManager", Configuration.GetSection("EchinoManagerOptions"));
        services.Configure<IdentityServerClientOptions>("EchinoProduct", Configuration.GetSection("EchinoProductOptions"));
        services.Configure<IdentityServerClientOptions>("WebInterface", Configuration.GetSection("WebInterfaceOptions"));

        // Add IdentityServerResources configuration
        services.Configure<APIOptions>(Configuration.GetSection("APIOptions"));
        services.Configure<APIScopeOptions>("ManageAPIScope", Configuration.GetSection("ManageAPIScopeOptions"));
        services.Configure<APIScopeOptions>("EchinoAPIScope", Configuration.GetSection("EchinoAPIScopeOptions"));
        services.Configure<APIScopeOptions>("WebInterfaceAPIScope", Configuration.GetSection("WebInterfaceAPIScopeOptions"));

        // Get X509Certificate
        X509Certificate2 cert = null;
        using (var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
        {
            certStore.Open(OpenFlags.ReadOnly);
            var certCollection = certStore.Certificates.Find(
                X509FindType.FindByThumbprint,
                Configuration.GetValue<string>("ApplicationOptions:CertificateThumbprint"),
                false);

            if (certCollection.Count > 0)
            {
                cert = certCollection[0];
            }
        }

        // Add the protection of the API
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;                // = Bearer
            options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;    // = Bearer
        })
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = Configuration.GetValue<string>("ApplicationOptions:AuthorityServer");
            options.ApiName = Configuration.GetValue<string>("APIOptions:Name");
            options.ApiSecret = Configuration.GetValue<string>("APIOptions:Secret");
        });

        // Add Identity Server 4
        services.AddIdentityServer()
            .AddSigningCredential(cert)
            .AddInMemoryPersistedGrants()
            .AddClientStore<ClientStore>()
            .AddResourceStore<ResourceStore>()
            .AddAspNetIdentity<User>();

        // Add policies based on scopes
        services.AddAuthorization(options =>
        {
            options.AddPolicy("ManageAPIScope", builder =>
              builder.RequireClaim("scope", Configuration.GetValue<string>("ManageAPIScopeOptions:Name")));
            options.AddPolicy("EchinoAPIScope", builder =>
              builder.RequireClaim("scope", Configuration.GetValue<string>("EchinoAPIScopeOptions:Name")));
            options.AddPolicy("WebMVCAPIScope", builder =>
              builder.RequireClaim("scope", Configuration.GetValue<string>("WebInterfaceAPIScopeOptions:Name")));
        });

        // Add OpenAPI
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("manageapi", new Info
            {
                Version = "1",
                Title = "Manage API",
                Description = "The API for Echino Manager"
            });

            c.SwaggerDoc("echinoapi", new Info
            {
                Version = "1",
                Title = "Echino API",
                Description = "The API for Echino"
            });

            c.DescribeAllEnumsAsStrings();

            c.AddSecurityDefinition("oauth2", new OAuth2Scheme
            {
                Type = "oauth2",
                Flow = "application",
                TokenUrl = $"{Configuration.GetValue<string>("ApplicationOptions:AuthorityServer")}/connect/token",
                Scopes = new Dictionary<string, string>
                {
                    { "manageapi", "Access to the manage api" }
                }
            });

            c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
            {
                { "oauth2", new[] { "manageapi" } }
            });

            // Set the comments path for the Swagger JSON and UI.
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/manageapi/swagger.json", "Manage API");
            c.SwaggerEndpoint("/swagger/echinoapi/swagger.json", "Echino API");
        });

        //app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
        app.UseIdentityServer();

        app.UseMvcWithDefaultRoute();
    }
}

使用MongoDB对Identity的调用:

        public static IServiceCollection AddIdentityMongoDbProvider<TUser, TRole>(this IServiceCollection services, Action<IdentityOptions> setupIdentityAction, Action<MongoIdentityOptions> setupDatabaseAction) where TUser : User where TRole : Role
    {
        services.AddIdentity<TUser, TRole>(setupIdentityAction ?? (x => { }))
            .AddRoleStore<RoleStore<TRole>>()
            .AddUserStore<UserStore<TUser, TRole>>()
            .AddDefaultTokenProviders();

        var dbOptions = new MongoIdentityOptions();
        setupDatabaseAction(dbOptions);

        var userCollection = new IdentityUserCollection<TUser>(dbOptions.DbType, dbOptions.ConnectionString);
        var roleCollection = new IdentityRoleCollection<TRole>(dbOptions.DbType, dbOptions.ConnectionString);

        // Add collections and stores in services for DI
        services.AddTransient<IIdentityUserCollection<TUser>>(x => userCollection);
        services.AddTransient<IIdentityRoleCollection<TRole>>(x => roleCollection);

        services.AddTransient<ITenantStore<Tenant, TUser>>(x => new TenantStore<Tenant, TUser>(dbOptions.DbType, dbOptions.ConnectionString, userCollection));
        services.AddTransient<ILicenseStore<License>>(x => new LicenceStore<License>(dbOptions.DbType, dbOptions.ConnectionString));

        // Identity Services
        services.AddTransient((Func<IServiceProvider, IUserStore<TUser>>)(x => new UserStore<TUser, TRole>(userCollection, roleCollection, x.GetService<ILookupNormalizer>())));
        services.AddTransient<IRoleStore<TRole>>(x => new RoleStore<TRole>(roleCollection));

        return services;
    }

当我评论“添加API保护”部分时,登录效果很好。

你们能告诉我/让我一起工作吗?

谢谢

这就是我的创业公司。

services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
            {
                options.Authority = authority;
                options.ApiName = "testapi";
                options.RequireHttpsMetadata = false;
            });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM