【发布时间】:2020-06-18 18:04:34
【问题描述】:
我有一个使用 IdentityServer 进行身份验证的 Asp.NET Core 应用程序。
这很好用。
现在我想在我的应用程序中使用 ASP.NET Core Identity 来管理角色、声明等。
文档说我应该为此添加service.AddIdentity ...。
但是,当我在客户端中将其添加到 Startup.cs 时,使用 IdentityServer 的登录不再有效。
我将被重定向到 IdentityServer,登录并重定向回客户端(这工作正常)
但是,然后我的客户端会引发有关授权的错误并再次重定向到 IdentityServer。这会导致无限循环
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST http://localhost:44331/signin-oidc application/x-www-form-urlencoded 5297
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies signed in.
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 184.9938ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:44331/
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: Identity.Application was not authenticated. Failure message: Unprotect ticket failed
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Index", controller = "Home", page = "", area = ""}. Executing action TestApplication.Controllers.HomeController.Index (TestApplication)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: AuthenticationScheme: oidc was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action TestApplication.Controllers.HomeController.Index (TestApplication) in 15.4912ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 29.286ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST http://localhost:44331/signin-oidc application/x-www-form-urlencoded 5297
-- and it starts all over again
有人知道我做错了什么吗?
这是我的 Startup.cs
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
var builder = new ConfigurationBuilder()
.SetBasePath(environment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{environment.EnvironmentName}.json", optional: true);
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
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.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<ApiService>();
services.AddSingleton(Configuration);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie()
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = 'Cookies';
options.UseTokenLifetime = true;
options.Authority = 'https://localhost:44350;
options.RequireHttpsMetadata = true;
options.ClientId = Configuration.GetValue<string>("IdentityServer:ClientId");
options.ClientSecret = Configuration.GetValue<string>("IdentityServer:ClientSecret");
options.ResponseType = "code id_token token"
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1");
options.Scope.Add("offline_access");
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
});
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore)
.AddJsonOptions(x => x.SerializerSettings.NullValueHandling = NullValueHandling.Ignore);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller}/{action}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
【问题讨论】:
-
您必须在您的身份服务器中配置 ASP.NET 身份,而不是在您的 MVC 应用程序中。用户将在那里登录(Id Server),它也可以管理角色,并将它们作为声明返回。在您的 MVC 应用程序中,您只需添加普通的
Policies即可根据角色在端点中应用授权。 -
所以你是说现在所有的用户管理等都应该在 IdentityServer 中完成?嗯,这很烦人。
-
不一定。您可以将 ASP.Identity 与它挂钩。这意味着它将从该数据库中读取并验证用户,并通过用户声明(角色)向您返回访问令牌。如果您愿意,可以使用其他应用程序来管理“身份”数据库。
-
是的,我的 IdentityServer 中有 ASP.Identity。我正在尝试在我的客户端应用程序中找到一种在不破坏登录机制的情况下使用和扩展 IdentityUser 的方法。
标签: asp.net-core asp.net-identity identityserver4