У меня есть эти настройки для сеанса в моем приложении ASP.NET Core Web Api для управления токенами XSRF. Приложение использует канал передачи jwt для входа в систему пользователей и файлы cookie XSRF для защиты общедоступных и не требующих входа API-методов.
services.AddAntiforgery(antiforgeryOptions =>
{
antiforgeryOptions.Cookie.SameSite = SameSiteMode.None;
antiforgeryOptions.HeaderName = "X-XSRF-TOKEN";
});
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromMinutes(20);
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
И мой AntiForgeryTokenMiddleware, как показано ниже:
public class AntiforgeryTokenMiddleware
{
private readonly RequestDelegate _next;
private readonly IAntiforgery _antiforgery;
public AntiforgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery)
{
_next = next;
_antiforgery = antiforgery;
}
public Task Invoke(HttpContext context)
{
string path = context.Request.Path.Value;
if (context.Request.Path.Value.IndexOf("/api", StringComparison.OrdinalIgnoreCase) != -1)
{
// The request token can be sent as a JavaScript-readable cookie,
// and Angular uses it by default.
var tokens = _antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions()
{
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None,
HttpOnly = false
});
}
return _next(context);
}
}
public static class AntiforgeryTokenMiddlewareExtensions
{
public static IApplicationBuilder UseAntiforgeryToken(this IApplicationBuilder builder)
{
return builder.UseMiddleware<AntiforgeryTokenMiddleware>();
}
}
ВВ моем приложении мне нужно отслеживать действия пользователя, и для этого я использую атрибут ActionFilterAttribute, как показано ниже:
public class PathRecorderActionFilter : ActionFilterAttribute
{
public string PathName { get; set; }
public async override void OnActionExecuting(ActionExecutingContext context)
{
IPathDataService _pathDataService = (IPathDataService)context.HttpContext.RequestServices.GetService(typeof(IPathDataService));
await _pathDataService.CreatePathData(new Model.PathData()
{
CreateDate = DateTime.Now,
NodeName = PathName,
SessionId = context.HttpContext.Session.Id // Session Id
// always
// changing
});
}
}
И использование выглядит так:
[PathRecorderActionFilter(PathName = "Projects")]
[AllowAnonymous]
[HttpGet("GetProjectsPublic/{term}/{designerId}/{categories}", Name = "GetProjectsPublic")]
public async Task<IActionResult> GetProjectsPublic(string term, long designerId, string categories, [FromQuery]UserParams userParams)
{
var projectPredicated = SearchPredicateBuilder.True<Project>();
if (term.Trim() != "filter=")
{
projectPredicated = projectPredicated.And(x => x.Name.Contains(term.Substring(7, term.Trim().Length - 7)));
}
if (designerId != -1)
{
projectPredicated = projectPredicated.And(x => x.CreateUserId == designerId);
}
if (categories.Split('_').Length > 0 && !categories.Contains("-1"))
{
string[] categoryList = categories.Split('_').ToArray();
var inner = SearchPredicateBuilder.False<Project>();
foreach (var item in categoryList)
{
inner = inner.Or(x => x.ProjectCategorySetList.Any( y => y.ProjectCategoryId.ToString() == item));
}
projectPredicated = projectPredicated.And(inner);
}
projectPredicated = projectPredicated.And(x => x.ProjectStatus == ProjectStatus.Approved);
List<Project> projects = await _projectService.GetProjects(filter: projectPredicated);
PagedList<Project> pagedListProjects = await PagedList<Project>.CreateAsync(projects, userParams.PageNumber, userParams.PageSize);
Response.AddPagination(userParams.PageNumber, userParams.PageSize, projects.LongCount(), 0);
return Ok(pagedListProjects);
}