Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 在ASP.NET核心Web API中使用无标识的cookie身份验证时,如何在登录时刷新CSRF令牌_Angular_Asp.net Core_Authentication_Asp.net Web Api_Csrf - Fatal编程技术网

Angular 在ASP.NET核心Web API中使用无标识的cookie身份验证时,如何在登录时刷新CSRF令牌

Angular 在ASP.NET核心Web API中使用无标识的cookie身份验证时,如何在登录时刷新CSRF令牌,angular,asp.net-core,authentication,asp.net-web-api,csrf,Angular,Asp.net Core,Authentication,Asp.net Web Api,Csrf,我有一个ASP.NET Core 3.1后端,带有angular 9前端(基于dotnet angular模板,只是将angular更新为v9)。 我使用cookie身份验证(我知道JWT更适合SPA,将此作为一个实验),并且我还添加了对服务器端CSRF保护的支持: services.AddAntiforgery(选项=> { options.HeaderName=“X-XSRF-TOKEN”;//角度csrf头名称 }); 我有服务器端设置,可以使用 options=>options.Fil

我有一个ASP.NET Core 3.1后端,带有angular 9前端(基于dotnet angular模板,只是将angular更新为v9)。 我使用cookie身份验证(我知道JWT更适合SPA,将此作为一个实验),并且我还添加了对服务器端CSRF保护的支持:

services.AddAntiforgery(选项=>
{
options.HeaderName=“X-XSRF-TOKEN”;//角度csrf头名称
});
我有服务器端设置,可以使用

options=>options.Filters.Add(新的AutoValidateAntiforgeryTokenAttribute())
所以GET请求不会根据CSRF进行检查,但POST会进行检查

在一开始,angular应用程序向
api/init
发出GET请求,以在引导之前获取一些初始数据。在服务器端,此操作初始化CSRF,如下所示:

//初始化操作体
var tokens=_antiForgery.GetAndStoreTokens(HttpContext);
Response.Cookies.Append(“XSRF-TOKEN”、tokens.RequestToken、新CookieOptions
{
HttpOnly=false
});
//返回一些初始数据DTO
这与预期的一样有效-GET响应包含2个CSRF cookie-第一个是ASP.NET core默认CSRF cookie
.AspNetCore.Antiforgery…
,第二个是
XSRF-TOKEN
,angular将读取并放入
X-XSRF-TOKEN
头中以供后续请求

如果之后我从angular应用程序登录(POST请求包含到
api/auth/login
)时,一切正常-请求被发布,包括
X-XSRF-TOKEN
头和CSRF验证通过,因此如果凭据正确,则用户登录

现在问题就从这里开始。ASP.NET服务器应用程序使用cookie身份验证,而不使用此处所述的标识。在登录操作中,还需要重新生成CSRF令牌,因为通过身份验证,CSRF令牌将启动,包括经过身份验证的用户标识。因此,我的登录操作如下所示:

公共异步任务登录(凭证到凭证)
{
//伪造用户凭据检查
if(credentials.Login!=“admin”| | credentials.Password!=“admin”)
{
未经授权返回();
}
var claimsIdentity=新的claimsIdentity(新[]
{
新索赔(ClaimTypes.Name,“theAdmin”),
},CookieAuthenticationDefaults.AuthenticationScheme);
var claimsPrincipal=新的claimsPrincipal(索赔实体);
等待HttpContext.SignInAsync(claimsPrincipal);
//登录时刷新反伪造令牌(与之前的初始化操作中的代码相同)
var tokens=_antiForgery.GetAndStoreTokens(HttpContext);
Response.Cookies.Append(“XSRF-TOKEN”、tokens.RequestToken、新CookieOptions
{
HttpOnly=false
});
返回新的JsonResult(新用户dto{Id=1,Login=“theAdmin”});
}
然而,这是行不通的。响应包含
XSRF-TOKEN
cookie,但是随后的POST请求(在我的例子中,它的logout=POST to
api/auth/logout
)以400失败,尽管正确地将此cookie值放入
X-XSRF-TOKEN
头中。 我认为原因是由于某种原因,响应中没有设置dafault
.AspNetCore.Antiforgery…
cookie,因此即使在登录后仍保留原始值,因此CSRF检查失败,因为值不匹配


如何正确地刷新CSRF令牌就是这样的场景?

在进行了更多的尝试和错误,并搜索了ASP.NET github并找到了和之后,似乎我想要实现的目标在单个请求中是不可行的,因为在单个请求处理过程中用户的身份不会改变(显然是出于设计)

使其工作的唯一方法(也称为登录/注销后刷新CSRF令牌)是在之后发出附加请求,其中CSRF令牌将根据新获取的身份正确刷新

我通过登录操作返回302重定向来实现这一点,随后执行CSRF刷新。注销时也需要这样做

副作用是请求量翻了一番,angular跟踪重定向可能会出现问题(我在Chrome中使用angular 9,但在互联网上有很多关于angular的HttpClient不跟踪重定向的抱怨)。此外,当登录请求成功时,您可能会处于一种不稳定状态,但由于某些原因,重定向到令牌刷新失败-然后您将使用过时的CSRF令牌。所以不太好,也不可怕