У меня есть проект ASP. NET Core 3.1 MVC, с простой системой аутентификации на основе файлов cookie и несколькими ролями и политиками. DI обрабатывается с помощью Autofa c (не внутренней системы DI ASP. NET Core).
Я знаю, что мой пользователь правильно загружен соответствующими ролями и вызывает внутренние методы, такие как Context.User.IsInRole("Administrator"))
(из представлений) работают должным образом.
Однако все мои AuthorizeAttribute
не работают, в зависимости от содержимого моего автозагрузки, кажется ли, что они ничего не делают, или я всегда перенаправлен на страницу входа (даже если правильное требование выполнено).
Аннотация, подобная
[Authorize(Policy = "Administrator,Collaborator")]
или простому
[Authorize(Roles = "Administrator")]
, помещенному в метод действия, кажется, ничего не делает.
Я знаю, что порядок вызовов при запуске Configure
и ConfigureServices
имеют большое значение, но, несмотря на множество попыток и много чтения подобных вопросов на SO или где-то еще, я не смог заставить его работать, как ожидалось.
Ниже я поделился всем моим файлом Startup
(извините за это), в надежде, что кто-нибудь сможет указать правильный порядок (или другой вид исправления, конечно), чтобы он работал для моего конкретного c случая.
Большое спасибо.
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddOptions();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
options.LoginPath = "/Account/Login";
options.SlidingExpiration = true;
options.ExpireTimeSpan = new TimeSpan(0, 24, 0, 0);
options.AccessDeniedPath = "/Error/RightError";
});
services.AddAuthorization(options =>
{
options.AddPolicy(SecurityPolicies.AdministratorOnly, policy =>
policy.RequireClaim(ClaimTypes.Role, UserRoles.Administrator));
options.AddPolicy(SecurityPolicies.AdministratorOrCollaborator, policy =>
policy.RequireClaim(ClaimTypes.Role, UserRoles.Administrator, UserRoles.Collaborator));
});
services.AddSession(options => options.IdleTimeout = TimeSpan.FromHours(4));
services.AddMvc(options => options.Filters.Add(new AuthorizeFilter()))
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddKendo();
}
// ConfigureContainer is where you can register things directly
// with Autofac. This runs after ConfigureServices so the things
// here will override registrations made in ConfigureServices.
// Don't build the container; that gets done for you by the factory.
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new MyFrontModule());
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseExceptionHandler(ProcessError);
}
else
{
app.UseExceptionHandler("/Error/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllers();
endpoints.MapRazorPages();
});
var ci = new CultureInfo("fr-FR")
{
NumberFormat = { NumberDecimalSeparator = ".", CurrencyDecimalSeparator = "." }
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(ci),
SupportedCultures = new List<CultureInfo> { ci },
SupportedUICultures = new List<CultureInfo> { ci }
});
}
private void ProcessError(IApplicationBuilder appError)
{
appError.Run(async context =>
{
// Not relevant for my question
});
}
}
Я также читал, что Json Сериализатор может что-то изменить, я использую Newtonsoft с DefaultContractResolver (как указано выше), и я использую компоненты интерфейса Telerik.
Большое спасибо за любые полезные советы!