У меня есть страница Razor с атрибутом:
[Authorize(Policy = "Staff")]
и следующая конфигурация авторизации:
options.AddPolicy("Staff", policy =>
{
policy.RequireAuthenticatedUser();
policy.AddAuthenticationSchemes("MyAdSchemeName");
policy.RequireRole("Staff");
});
При переходе на эту страницу меня правильно перенаправляет на страницу входа в систему, однако URL-адрес возврата, передаваемый в качестве параметра строки запроса, равен Account/AccessDenied
.
Я чувствую, что, может быть, я что-то упускаю, но это кажется неправильным, поскольку, безусловно, необходимо пройти аутентификацию, прежде чем можно будет определить, следует ли возвращать 403?
Я ожидаю (что может быть ошибочным), что переход на страницу в качестве неаутентифицированного пользователя должен перенаправляться на страницу входа в систему, вход в систему обрабатывается (т.е. получаются роли), а затем перенаправляется обратно на первоначально запрошенную страницу, где он затем может определить есть ли у них доступ (т.е. необходимая роль)?
Когда я удаляю вызов RequireRole
против определения политики, он работает, но, очевидно, разрешает всем аутентифицированным пользователям независимо от роли.
Кстати, Account/AccessDenied
даже не существует в моем приложении, и я не вижу, как его изменить. Я пробовал следующее, но безрезультатно:
services.Configure<CookieAuthenticationOptions>("MyAdSchemeName", options => options.AccessDeniedPath = "/errors/403");
Код программы.cs:
var authentication = services.AddAuthentication();
authentication
.AddMicrosoftIdentityWebApp(
configuration.GetSection("AdConfig"),
openIdConnectScheme: "MyAdSchemeName",
cookieScheme: null,
displayName: "MyAdSchemeName");
services.Configure<CookieAuthenticationOptions>("MyAdSchemeName", options => options.AccessDeniedPath = "/errors/403");
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = 403;
return Task.FromResult(0);
}
};
options.AccessDeniedPath = "/errors/403";
options.LoginPath = new PathString("/login");
});
services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
options.AddPolicy(PolicyNames.Staff, policy =>
{
policy.RequireAuthenticatedUser();
policy.AddAuthenticationSchemes("MyAdSchemeName");
policy.RequireRole("Staff");
});
});
На самом деле, здесь задано множество вопросов и задействованы различные факторы, так почему бы нам не сделать шаг назад, немного очистить конфигурацию и начать с рабочего примера:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
// staff authentication policy
options.AddPolicy("Staff", policy =>
{
policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme);
policy.RequireClaim(ClaimTypes.Role, "Staff");
});
});
Выше приведена конфигурация:
Account/AccessDenied
— это одно из перенаправлений по умолчанию для ASP.NET Core Identity, а представление с тем же именем обычно находится в папке Views
. Если вы хотите изменить это, измените приведенный выше пример следующим образом:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.AccessDeniedPath = "...";
});
Дополнительно: помимо использования атрибута Authorize
вы можете применить политику «Персонал» ко всей области, что мне кажется очень удобным:
endpoints.MapControllerRoute(
name: "Staff",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization("Staff");
Я надеюсь, что это поможет и что вы сможете дополнительно настроить его в соответствии со своими потребностями.
Страница Account/AccessDenied происходит из основной части идентификации asp.net в вашем проекте, но вы ее не показали. Вам необходимо изменить конфигурацию входа, чтобы можно было переопределить перенаправление.
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
options.AccessDeniedPath = "/errors/403";
});
При попадании на страницу без входа пользователя.
После входа в систему.
можешь поделиться программой.cs и как прописываешь аутентификацию и авторизацию?