我使用IAntiforgery
apis创建了一个ASP.Net Core 2应用程序。
这提供了一种返回cookie的方法。
客户端获取该cookie,并在随后的POST请求中将该值放入X-XSRF-TOKEN头中。
中间件验证了这一点,并允许请求在失败时继续或不继续。
如果在请求中发送了正确的Cookie和标头,则始终无法通过验证,我不明白为什么。
整个复制在https://github.com/jchannon/AntiForgery
但是,主要问题区域如下。
public class Startup
{
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery, ILoggerFactory loggerFactory)
{
app.UseAuthentication();
app.Use(async (context, next) =>
{
var logger = loggerFactory.CreateLogger("ValidRequestMW");
//Don't validate POST for login
if (context.Request.Path.Value.Contains("login"))
{
await next();
return;
}
logger.LogInformation(context.Request.Cookies["XSRF-TOKEN"]);
logger.LogInformation(context.Request.Headers["X-XSRF-TOKEN"]);
//On POST requests it will validate the XSRF header
if (!await antiforgery.IsRequestValidAsync(context))
{
/****************************************************
*
*
* For some reason when the cookie and the header are sent in on the /create POST this validation always fails
*
*
***************************************************/
context.Response.StatusCode = 401;
logger.LogError("INVALID XSRF TOKEN");
return;
}
await next();
});
app.UseRouter(r =>
{
r.MapGet("", async context => { await context.Response.WriteAsync("hello world"); });
//This returns a XSRF-TOKEN cookie
//Client will take this value and add it as a X-XSRF-TOKEN header and POST to /create
r.MapPost("login", async (context) =>
{
antiforgery.SetCookieTokenAndHeader(context);
context.Response.Redirect("/");
});
//If XSRF validaiton is correct we should hit this route
r.MapPost("create", async context =>
{
context.Response.StatusCode = 201;
await context.Response.WriteAsync("Created");
});
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(x => x.AddConsole());
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
options.Cookie.Name = "XSRF-TOKEN";
options.Cookie.HttpOnly = false;
});
// services.AddAuthentication("MyCookieMW")
// .AddCookie("MyCookieMW", cookieOptions =>
// {
// cookieOptions.Cookie.Name = "MyCookie";
// cookieOptions.Cookie.HttpOnly = true;
// cookieOptions.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
// cookieOptions.SlidingExpiration = true;
// });
services.AddRouting();
}
}
答案 0 :(得分:1)
因此深入研究了防伪的源代码和一些命名不当的方法(SetCookieTokenAndHeader
我正在看着你)。正确的代码应该是:
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery, ILoggerFactory loggerFactory)
{
app.Use(async (context, next) =>
{
var logger = loggerFactory.CreateLogger("ValidRequestMW");
//Don't validate POST for login
if (context.Request.Path.Value.Contains("login"))
{
await next();
return;
}
logger.LogInformation("Request Cookie is " + context.Request.Cookies["XSRF-TOKEN"]);
logger.LogInformation("Request Header is " + context.Request.Headers["X-XSRF-TOKEN"]);
//On POST requests it will validate the XSRF header
if (!await antiforgery.IsRequestValidAsync(context))
{
context.Response.StatusCode = 401;
logger.LogError("INVALID XSRF TOKEN");
return;
}
await next();
});
app.UseRouter(r =>
{
r.MapGet("", async context => { await context.Response.WriteAsync("hello world"); });
//This returns a XSRF-TOKEN cookie
//Client will take this value and add it as a X-XSRF-TOKEN header and POST to /create
r.MapPost("login", async (context) =>
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
context.Response.Redirect("/");
});
//If XSRF validaiton is correct we should hit this route
r.MapPost("create", async context =>
{
context.Response.StatusCode = 201;
await context.Response.WriteAsync("Created");
});
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAntiforgeryTokenGenerator, MyTokenGenerator>();
services.AddSingleton<IAntiforgery, MyAntiforgery>();
services.AddLogging(x => x.AddConsole());
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
options.Cookie.Name = "MyAntiforgery";
options.Cookie.HttpOnly = false;
});
services.AddRouting();
}