ASP.NET Core 2.0 - 用户在一小时内注销
ASP.NET Core 2.0 - users are logged out within an hour
几天前,我将我的代码发布到 "production" 环境中,仅用于测试目的。所以这个我一直在开发的网站是在线的。问题是无论我对 cookie 设置做了什么更改。
我尝试将滑动过期更改为 true 和 false,两者都使用:
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Expiration = TimeSpan.FromDays(30);
还将有效期设置为 1 年。
似乎没有任何效果。
这是我在 Startup.cs 中的设置:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.RequireHeaderSymmetry = false;
});
services.AddDbContext<IdentityDataContext>();
services.AddIdentity<PinchilaIdentityUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityDataContext>()
.AddUserManager<PinchilaUserManager>()
.AddDefaultTokenProviders();
services.Configure<SecurityStampValidatorOptions>(options => options.ValidationInterval = TimeSpan.FromSeconds(10));
services.AddAuthentication()
.Services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
});
}
//COOKIE
services.ConfigureApplicationCookie(options => {
if (!String.IsNullOrEmpty(PinchilaSettings.Instance.CookieDomain))
{
options.Cookie.Domain = PinchilaSettings.Instance.CookieDomain;
}
if (!String.IsNullOrEmpty(PinchilaSettings.Instance.CookieName))
{
options.Cookie.Name = PinchilaSettings.Instance.CookieName;
}
options.AccessDeniedPath = new PathString("/error/default");
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Expiration = TimeSpan.FromDays(30);
});
var mvcBuilder = services.AddMvc();
services.Configure<RazorViewEngineOptions>(options => {
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
mvcBuilder.AddMvcOptions(o => {
o.Filters.Add(typeof(GlobalExceptionFilter));
o.Filters.Add(typeof(RuntimeStateFilter));
o.Filters.Add(typeof(RouteLoggerFilter));
});
services.AddAntiforgery(options => {
options.HeaderName = Utilities.CONSTANTS.REQUEST_VERIFICATION_HEADER_NAME;
options.FormFieldName = Utilities.CONSTANTS.REQUEST_VERIFICATION_HEADER_NAME;
});
services.AddScoped<IViewRenderService, ViewRenderService>();
services.AddLogging(loggingBuilder =>
{
var filter = new LoggingFilter();
loggingBuilder.AddFilter(filter.Filter);
});
}
这是我的 AccountController 登录部分:
[HttpPost]
[AllowAnonymous]
[PinchilaValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
model.UserName = model.UserName.TrimSafe();
model.Password = model.Password.TrimSafe();
var user = await _userManager.FindByNameAsync(model.UserName);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
var cookie = HttpContext.Request.Cookies["theme"];
if (cookie != null && !String.IsNullOrEmpty(cookie))
{
Response.Cookies.Append("theme", "", new Microsoft.AspNetCore.Http.CookieOptions() { Expires = DateTime.UtcNow.AddDays(30) });
}
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
ModelState.AddModelError(string.Empty, "This account has been locked out for security reasons. Try again later.");
return View(model);
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt");
return View(model);
}
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt");
}
}
return View(model);
}
如果你们中的任何人能给我一些不同的观点,我将不胜感激。
编辑:这是 cookie 在 Chrome 控制台上的样子:
感谢@TiagoBrenck 的评论,我开始在服务器端寻找答案。
我发现了 。请查看@dantey89 的回答。它解决了我的问题。
基本上,在 startup.cs 中,您需要在 ConfigureServices 方法中添加:
public void ConfigureServices(IServiceCollection services)
{
var environment = services.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();
services.AddDataProtection()
.SetApplicationName($"my-app-{environment.EnvironmentName}")
.PersistKeysToFileSystem(new DirectoryInfo($@"{environment.ContentRootPath}\keys"));
...
}
这将创建一个文件夹。它需要来自应用程序池的权限,否则将出现错误 500。
希望这对其他人有帮助。
几天前,我将我的代码发布到 "production" 环境中,仅用于测试目的。所以这个我一直在开发的网站是在线的。问题是无论我对 cookie 设置做了什么更改。
我尝试将滑动过期更改为 true 和 false,两者都使用:
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Expiration = TimeSpan.FromDays(30);
还将有效期设置为 1 年。 似乎没有任何效果。
这是我在 Startup.cs 中的设置:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.RequireHeaderSymmetry = false;
});
services.AddDbContext<IdentityDataContext>();
services.AddIdentity<PinchilaIdentityUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityDataContext>()
.AddUserManager<PinchilaUserManager>()
.AddDefaultTokenProviders();
services.Configure<SecurityStampValidatorOptions>(options => options.ValidationInterval = TimeSpan.FromSeconds(10));
services.AddAuthentication()
.Services.ConfigureApplicationCookie(options =>
{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
});
}
//COOKIE
services.ConfigureApplicationCookie(options => {
if (!String.IsNullOrEmpty(PinchilaSettings.Instance.CookieDomain))
{
options.Cookie.Domain = PinchilaSettings.Instance.CookieDomain;
}
if (!String.IsNullOrEmpty(PinchilaSettings.Instance.CookieName))
{
options.Cookie.Name = PinchilaSettings.Instance.CookieName;
}
options.AccessDeniedPath = new PathString("/error/default");
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Expiration = TimeSpan.FromDays(30);
});
var mvcBuilder = services.AddMvc();
services.Configure<RazorViewEngineOptions>(options => {
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
mvcBuilder.AddMvcOptions(o => {
o.Filters.Add(typeof(GlobalExceptionFilter));
o.Filters.Add(typeof(RuntimeStateFilter));
o.Filters.Add(typeof(RouteLoggerFilter));
});
services.AddAntiforgery(options => {
options.HeaderName = Utilities.CONSTANTS.REQUEST_VERIFICATION_HEADER_NAME;
options.FormFieldName = Utilities.CONSTANTS.REQUEST_VERIFICATION_HEADER_NAME;
});
services.AddScoped<IViewRenderService, ViewRenderService>();
services.AddLogging(loggingBuilder =>
{
var filter = new LoggingFilter();
loggingBuilder.AddFilter(filter.Filter);
});
}
这是我的 AccountController 登录部分:
[HttpPost]
[AllowAnonymous]
[PinchilaValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
model.UserName = model.UserName.TrimSafe();
model.Password = model.Password.TrimSafe();
var user = await _userManager.FindByNameAsync(model.UserName);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
var cookie = HttpContext.Request.Cookies["theme"];
if (cookie != null && !String.IsNullOrEmpty(cookie))
{
Response.Cookies.Append("theme", "", new Microsoft.AspNetCore.Http.CookieOptions() { Expires = DateTime.UtcNow.AddDays(30) });
}
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
ModelState.AddModelError(string.Empty, "This account has been locked out for security reasons. Try again later.");
return View(model);
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt");
return View(model);
}
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt");
}
}
return View(model);
}
如果你们中的任何人能给我一些不同的观点,我将不胜感激。
编辑:这是 cookie 在 Chrome 控制台上的样子:
感谢@TiagoBrenck 的评论,我开始在服务器端寻找答案。
我发现了
基本上,在 startup.cs 中,您需要在 ConfigureServices 方法中添加:
public void ConfigureServices(IServiceCollection services)
{
var environment = services.BuildServiceProvider().GetRequiredService<IHostingEnvironment>();
services.AddDataProtection()
.SetApplicationName($"my-app-{environment.EnvironmentName}")
.PersistKeysToFileSystem(new DirectoryInfo($@"{environment.ContentRootPath}\keys"));
...
}
这将创建一个文件夹。它需要来自应用程序池的权限,否则将出现错误 500。
希望这对其他人有帮助。