我可以使用 HTTP 而不是 HTTPS 来托管 MVC 客户端以使用 IdentityServer 吗?
Can I use HTTP instead of HTTPS to host MVC client to work with IdentityServer?
我的快速启动程序在我的本地测试环境中运行:一个 MVC 客户端通过 IdentityServer 访问 API。这都是使用 HTTPS 和 self-host
(Kestrel) 进行的设置。我想知道的是 - 在使用 IdentityServer 时,我可以在 HTTP 而不是 HTTPS 中托管 MVC 吗?当我将 MVC 从 https://localhost:5009
更改为 http://localhost:5008
(在几个地方)后,如果我将所有各方更改为使用 HTTP 或仅使用 MVC 而将其余部分保留为 HTTPS,这似乎并不重要,应用程序因错误 "invalid redirect uri"
.
而失败
我是不是遗漏了什么,或者这只是不允许的事情?
您可以 运行 在开发期间很好地通过 HTTP,但在生产中您应该始终尝试使用 HTTPS。
您收到的错误是因为 IdentityServer 中客户端定义中的重定向URL与您客户端的url不匹配:
RedirectUris =
{
"https://localhost:5001/...."
},
如果您想在定义 OpenIDConnect 选项时使用 HTTP,还建议在客户端中将此设置为 false。
/// <summary>
/// Gets or sets if HTTPS is required for the metadata address or authority.
/// The default is true. This should be disabled only in development environments.
/// </summary>
public bool RequireHttpsMetadata { get; set; } = true;
如果您设法进入 IdentityServer 登录页面,那么在 URL 中您会发现实际发送到 IdentityServer 的重定向URL。或者使用 fiddler 捕获请求以查看传递给 identityserver 的 requestUrl 是什么。
当我查看屏幕截图时,allowedRedirectURis 中有端口 5009,请求中有 5008。
这是我的 MVC Startup
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.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
// The default is true. This should be disabled only in development environments!!!
options.RequireHttpsMetadata = false;
options.Authority = "https://localhost:5005";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("profile");
options.Scope.Add("email");
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("MyAPI");
options.Scope.Add("offline_access");
});
}
// 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();
}
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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization();
});
}
}
这是 IdentityServer 的启动
public class Startup
{
public IWebHostEnvironment Environment { get; }
public IConfiguration Configuration { get; }
public Startup(IWebHostEnvironment environment, IConfiguration configuration)
{
Environment = environment;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
var connstr = Configuration.GetConnectionString("MyIDSConnection");
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connstr));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.EmitStaticAudienceClaim = true;
})
.AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connstr,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connstr,
sql => sql.MigrationsAssembly(migrationsAssembly));
});
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
//services.AddIdentityServer().AddSigningCredential(
// new X509Certificate2(Path.Combine(_environment.ContentRootPath, "certs", "IdentityServer4Auth.pfx")));
services.AddAuthentication()
.AddGoogle(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
// register your IdentityServer with Google at https://console.developers.google.com
// enable the Google+ API
// set the redirect URI to https://localhost:5001/signin-google
options.ClientId = "";
options.ClientSecret = "";
});
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
// uncomment if use MVC
app.UseStaticFiles();
app.UseRouting();
// Add IdentityServer to the pipeline
// UseIdentityServer includes a call to UseAuthentication, so it’s not necessary to have both
app.UseIdentityServer();
// uncomment if use MVC
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
private void InitializeDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.Clients)
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.IdentityResources)
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
foreach (var resource in Config.ApiScopes)
{
context.ApiScopes.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
}
}
这是启动时的 IdentityServer 控制台 window
这是启动时的 MVC 控制台 window
我的快速启动程序在我的本地测试环境中运行:一个 MVC 客户端通过 IdentityServer 访问 API。这都是使用 HTTPS 和 self-host
(Kestrel) 进行的设置。我想知道的是 - 在使用 IdentityServer 时,我可以在 HTTP 而不是 HTTPS 中托管 MVC 吗?当我将 MVC 从 https://localhost:5009
更改为 http://localhost:5008
(在几个地方)后,如果我将所有各方更改为使用 HTTP 或仅使用 MVC 而将其余部分保留为 HTTPS,这似乎并不重要,应用程序因错误 "invalid redirect uri"
.
而失败
我是不是遗漏了什么,或者这只是不允许的事情?
您可以 运行 在开发期间很好地通过 HTTP,但在生产中您应该始终尝试使用 HTTPS。
您收到的错误是因为 IdentityServer 中客户端定义中的重定向URL与您客户端的url不匹配:
RedirectUris =
{
"https://localhost:5001/...."
},
如果您想在定义 OpenIDConnect 选项时使用 HTTP,还建议在客户端中将此设置为 false。
/// <summary>
/// Gets or sets if HTTPS is required for the metadata address or authority.
/// The default is true. This should be disabled only in development environments.
/// </summary>
public bool RequireHttpsMetadata { get; set; } = true;
如果您设法进入 IdentityServer 登录页面,那么在 URL 中您会发现实际发送到 IdentityServer 的重定向URL。或者使用 fiddler 捕获请求以查看传递给 identityserver 的 requestUrl 是什么。
当我查看屏幕截图时,allowedRedirectURis 中有端口 5009,请求中有 5008。
这是我的 MVC Startup
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.DefaultMapInboundClaims = false;
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
// The default is true. This should be disabled only in development environments!!!
options.RequireHttpsMetadata = false;
options.Authority = "https://localhost:5005";
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("profile");
options.Scope.Add("email");
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("MyAPI");
options.Scope.Add("offline_access");
});
}
// 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();
}
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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization();
});
}
}
这是 IdentityServer 的启动
public class Startup
{
public IWebHostEnvironment Environment { get; }
public IConfiguration Configuration { get; }
public Startup(IWebHostEnvironment environment, IConfiguration configuration)
{
Environment = environment;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
var connstr = Configuration.GetConnectionString("MyIDSConnection");
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connstr));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.EmitStaticAudienceClaim = true;
})
.AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connstr,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connstr,
sql => sql.MigrationsAssembly(migrationsAssembly));
});
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
//services.AddIdentityServer().AddSigningCredential(
// new X509Certificate2(Path.Combine(_environment.ContentRootPath, "certs", "IdentityServer4Auth.pfx")));
services.AddAuthentication()
.AddGoogle(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
// register your IdentityServer with Google at https://console.developers.google.com
// enable the Google+ API
// set the redirect URI to https://localhost:5001/signin-google
options.ClientId = "";
options.ClientSecret = "";
});
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
// uncomment if use MVC
app.UseStaticFiles();
app.UseRouting();
// Add IdentityServer to the pipeline
// UseIdentityServer includes a call to UseAuthentication, so it’s not necessary to have both
app.UseIdentityServer();
// uncomment if use MVC
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
private void InitializeDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.Clients)
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.IdentityResources)
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
foreach (var resource in Config.ApiScopes)
{
context.ApiScopes.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
}
}
这是启动时的 IdentityServer 控制台 window
这是启动时的 MVC 控制台 window