Я хочу использовать JWT-аутентификацию для моего веб-API и куки-аутентификацию для страниц Razor вместе.Я использую политику авторизации для контроллеров.Все работает для моих страниц Razor с этой конфигурацией в моих Startup.cs
:
services.AddIdentity<User, Role>(opt =>{
opt.Password.RequireDigit = false;
opt.Password.RequiredLength = 4;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireLowercase = false;
})
.AddEntityFrameworkStores<DataContext>()
.AddRoleValidator<RoleValidator<Role>>()
.AddRoleManager<RoleManager<Role>>()
.AddSignInManager<SignInManager<User>>();
Но мои конечные точки контроллера не работают, и когда я использую нижнюю, она работает:
IdentityBuilder builder = services.AddIdentityCore<User>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequiredLength = 4;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireLowercase = false;
});
Но роли не добавляются в заявки пользователей, и поэтому атрибуты политики авторизации для моих страниц Razor всегда возвращают Access Denied
.
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.AddDbContext<DataContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
options.SlidingExpiration = true;
options.Cookie.Name = Configuration.GetSection("AppSettings:AuthCookieName").Value;
});
// services.AddIdentity<User, Role>(opt =>{
// opt.Password.RequireDigit = false;
// opt.Password.RequiredLength = 4;
// opt.Password.RequireNonAlphanumeric = false;
// opt.Password.RequireUppercase = false;
// opt.Password.RequireLowercase = false;
// });
IdentityBuilder builder = services.AddIdentityCore<User>(opt =>
{
opt.Password.RequireDigit = false;
opt.Password.RequiredLength = 4;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireLowercase = false;
});
builder = new IdentityBuilder(builder.UserType, typeof(Role), builder.Services);
builder.AddEntityFrameworkStores<DataContext>();
builder.AddRoleValidator<RoleValidator<Role>>();
builder.AddRoleManager<RoleManager<Role>>();
builder.AddSignInManager<SignInManager<User>>();
services.AddAuthorization(options =>{
options.AddPolicy("CorrectUserIdRequested", policy=>{
policy.AddRequirements(new CorrectUserIdRequestedRequirement());
});
options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("admin"));
options.AddPolicy("RequireUserRole", policy => policy.RequireRole("admin","user"));
});
services.AddMvc(options => {
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).
SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
// Authentication Scheme
services.AddAuthentication(IdentityConstants.ApplicationScheme)
.AddCookie(IdentityConstants.ApplicationScheme, options =>
{
//if url start with "/api" use jwt instead
options.ForwardDefaultSelector = httpContext => httpContext.Request.Path.StartsWithSegments("/api") ? JwtBearerDefaults.AuthenticationScheme : null;
})
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
Mapper.Reset();
services.AddCors();
services.AddAutoMapper(typeof(Startup));
//Injections
services.AddTransient<Seed>();
services.AddScoped<AuthService, AuthServicePasswordless>();
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<INotificationService, SmsNotifyService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, Seed seeder)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder => {
builder.Run(async context => {
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var error = context.Features.Get<IExceptionHandlerFeature>();
if(error != null){
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message);
}
});
}); // 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.UseCookiePolicy();
seeder.SeedUsers();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: null,
template: "{area:exists}/{controller=Dashboard}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
//Controller
[Authorize(Policy = "RequireAdminRole")]
[Area("Admin")]
public class DashboardController : Controller
{
public IActionResult Index(){
return View();
}
}