【发布时间】:2020-07-24 08:42:34
【问题描述】:
问题
我有三个项目。
- 一个网络应用程序
- API
- 身份服务器
我遇到的问题是,当我将授权属性添加到 api 控制器时,我无法访问 API。
这是来自身份服务器的配置文件
public class Config
{
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "Stephen",
Password = "Password",
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.Role, "admin")
}
}
};
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource
{
Name = "role",
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<ApiResource> GetAllApiResources()
{
return new List<ApiResource>
{
new ApiResource
{
Name = "crmApi",
DisplayName = "API #1",
Description = "Allow the application to access API #1 on your behalf",
Scopes = new List<string> {"crmApi"},
ApiSecrets = new List<Secret> {new Secret("secret".Sha256())}, // change me!
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<ApiScope> GetApiScopes()
{
return new[]
{
new ApiScope("crmApi", "Access to API #1"),
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "crmApi" }
},
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
RedirectUris = {"https://localhost:44315/signin-oidc"},
PostLogoutRedirectUris = {"https://localhost:44315/signout-callback-oidc"},
AllowedScopes =new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"crmApi"
}
},
};
}
}
这是身份服务器启动文件
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.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(option => option.EnableEndpointRouting = false);
var connectionString = Configuration.GetSection("ConnectionStrings:Database").Value;
var migrationAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<ApplicationDbContext>(builder =>
builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationAssembly)));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationAssembly));
})
.AddAspNetIdentity<IdentityUser>();
services.AddCors();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
InitialISDatabase(app);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });
app.UseCors();
app.UseMvcWithDefaultRoute();
}
private void InitialISDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>().Database.Migrate();
serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
if (!context.Clients.Any())
{
foreach (var client in Config.GetClients())
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.GetIdentityResources())
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
foreach (var scope in Config.GetApiScopes())
{
context.ApiScopes.Add(scope.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiResources.Any())
{
foreach (var api in Config.GetAllApiResources())
{
context.ApiResources.Add(api.ToEntity());
}
context.SaveChanges();
}
var userManager = serviceScope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
if (!userManager.Users.Any())
{
foreach (var testUser in Config.GetUsers())
{
var identityUser = new IdentityUser(testUser.Username)
{
Id = testUser.SubjectId
};
userManager.CreateAsync(identityUser, "Password123!").Wait();
userManager.AddClaimsAsync(identityUser, testUser.Claims.ToList()).Wait();
}
}
}
}
}
这里是api启动文件。
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.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44302/";
options.ApiName = "crmApi";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
这里是 web 项目的启动文件。
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.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://localhost:44302/";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.SaveTokens = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
【问题讨论】:
-
发布您的 api 启动。
-
我做到了。它说这是我的 api 启动
-
尝试将 [Authorize(AuthenticationSchemes="Bearer")] 添加到控制器。
-
我删除了 .AddTestUsers(Config.GetUsers()) 并将属性添加到控制器。身份服务器说用户未通过身份验证,但存在于数据库中
-
看这里,像这里一样为启动添加身份验证,github.com/LalitaCode/IdentityServerSubdomainMultiTenant/blob/…
标签: c# identityserver4