【发布时间】:2020-11-22 11:36:33
【问题描述】:
我正在使用带有 Identity 的 Asp.Net Core 3.1。这是我在 Startup 类中的所有配置。 如果他们的帐户在使用该应用程序时过期,我正在尝试强制登录用户注销。我应该正确配置 cookie,但在使用 AddIdentity 时我被困在如何做到这一点。
这是我的启动
// 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.AddIdentity<IdentityUser, IdentityRole>(options => {
options.SignIn.RequireConfirmedAccount = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityCore<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
//.AddDefaultTokenProviders()
.AddDefaultUI();
services.AddSingleton<IEmailSender, EmailSender>();
services.Configure<EmailOptions>(Configuration);
services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddHangfireServer();
services.AddControllersWithViews(); //?
services.AddRazorPages().AddRazorRuntimeCompilation(); //?
services.AddScoped<IExpirationJob, ExpirationJob>();
services.AddScoped<IReminderJob, EmailReminder>();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.Configure<IdentityOptions>(options =>
{
// Password settings.
//options.Password.RequireDigit = true;
//options.Password.RequireLowercase = true;
//options.Password.RequireNonAlphanumeric = true;
//options.Password.RequireUppercase = true;
//options.Password.RequiredLength = 6;
//options.Password.RequiredUniqueChars = 1;
// Lockout settings.
//options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
//options.Lockout.MaxFailedAccessAttempts = 5;
//options.Lockout.AllowedForNewUsers = true;
// User settings.
//options.User.AllowedUserNameCharacters =
// "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+ ";
//options.User.RequireUniqueEmail = false;
});
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "my.Cookie";
config.LoginPath = "/Home/Login";
config.AccessDeniedPath = "/Identity/Account/AccessDenied";
config.Cookie.HttpOnly = true;
config.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env,
IRecurringJobManager recurringJobManager,
IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
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.UseHangfireDashboard();
//app.UseHangfireDashboard("/hangfire", new DashboardOptions()
//{
// Authorization = new[] { new CustomAuthorizeFilter() }
//});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseAuthentication();
app.UseAuthorization();
recurringJobManager.AddOrUpdate(
"End Users Subscription",
() => serviceProvider.GetService<IExpirationJob>().SetExpired(),
Cron.Minutely
);
recurringJobManager.AddOrUpdate(
"Send End of Subscription Reminder",
() => serviceProvider.GetService<IReminderJob>().SendReminder(),
Cron.Daily
);
app.Use(async (context, next) =>
{
_ = ExpirationJob.SetExpired(context);//pass the HttpContext to SetExpired
await next();
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
这是我的 ValidateAsync 类
public class ValidateAsync
{
public static async Task ValidatingAsync(CookieValidatePrincipalContext context)
{
context = context ?? throw new ArgumentNullException(nameof(context));
var claimsIdentity = context.Principal.Identity as ClaimsIdentity;
if (claimsIdentity?.Claims == null || !claimsIdentity.Claims.Any())
{
await RejectPrincipal();
return;
}
UserManager<IdentityUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>();
var user = await userManager.FindByNameAsync(context.Principal.FindFirstValue(ClaimTypes.NameIdentifier));
if (user == null || user.SecurityStamp != context.Principal.FindFirst(new ClaimsIdentityOptions().SecurityStampClaimType)?.Value)
{
await RejectPrincipal();
return;
}
async Task RejectPrincipal()
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
这是我的 SetExpired 方法
public interface IExpirationJob
{
Task SetExpired();
}
public class ExpirationJob : IExpirationJob
{
private readonly ApplicationDbContext _db;
private readonly IEmailSender _emailSender;
private readonly HttpContext _context;
public ExpirationJob(ApplicationDbContext db, IEmailSender emailSender, HttpContext context)
{
_db = db;
_emailSender = emailSender;
_context = context;
}
public async Task SetExpired()
{
foreach(var item in _db.Institution)
{
if (item.SubsEndDate != null)
{
if (item.SubsEndDate <= DateTime.Now)
{
item.Status = SD.StatusExpired;
Guid securityStamp = Guid.NewGuid();
item.Admin.SecurityStamp = securityStamp.ToString();
_context.Response.Cookies.Append("my.Cookie", "expired");
}
}
}
await _db.SaveChangesAsync();
}
}
【问题讨论】:
标签: c# .net asp.net-mvc asp.net-core cookies