本文介绍了根据CSRF攻击,ASP.NET核心角度Web应用程序中的ValiateAntiForgeryToken终结点属性用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web应用程序,它使用ASP.NET核心(3.1)后端和角度前端(8.2.11)。它使用ASP.NET身份框架进行用户身份验证。它将身份验证令牌存储在本地存储中,以用作请求中身份验证头。Sense控制器中的一切都在运行,只有当用户登录时才能访问终结点,如果注销,则直接在浏览器中键入终结点将被拒绝。

我仍然不确定这样的设置是否可以防止跨站点请求伪造(XSRF/CSRF)攻击。我知道使用Cookie存储身份验证令牌容易受到CSRF的影响,我在一些端点上尝试了一下[ValidateAntiForgeryToken]属性,当然它破坏了这些端点。我知道在剃刀页面中,一张表格会自动注入防伪令牌。那么,我需要在我的棱角前端设置它吗?如果是,又是如何做到的?(我在网上搜索了一下,说明到处都是,相当混乱,没有明确的共识)。

推荐答案

第1步

将一个中间件添加到您的中间件管道中,该中间件将生成一个AntiforgeryToken,并将该令牌嵌入到一个附加到响应的非纯http cookie中:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddAntiforgery(options => {
            options.HeaderName = "X-XSRF-TOKEN";
        });
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
    {
        ...;
        app.Use((context, next) => {
            var tokens = antiforgery.GetAndStoreTokens(httpContext);
            httpContext.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { Path = "/", HttpOnly = false });
        });
    }
}

我为此创建了a little package,其中包含此中间件。

第2步

配置您的ANGLE应用程序通过Java脚本读取非http-only cookie(XSRF-TOKEN)的值,并将该值作为HttpClient发送的请求的X-XSRF-TOKEN头传递:

@NgModule({
  declarations: [...],
  imports: [
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-XSRF-TOKEN'
    }),
    ...
  ],
  providers: [...],
  bootstrap: [AppComponent]
})
export class AppModule { }

第3步

现在您可以使用[ValidateAntiforgeryToken]属性:

来修饰您的控制器方法
[ApiController]
[Route("web/v1/[controller]")]
public class PersonController : Controller
{
    private IPersonService personService;
    public PersonController(IPersonService personService)
    {
        this.personService = personService;
    }
    
    [HttpPost]
    [Authorize]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult<Person>> Post([FromBody] Person person)
    {
        var new_person = await personService.InsertPerson(person);
        return Ok(new_person);
    }
}

第4步

确保您发送的请求具有以下类型的urlas stated here

  • /my/url
  • //example.com/my/url

错误的URL:

  • https://example.com/my/url

注意:

我使用身份Cookie身份验证:

services.AddAuthentication(/* No default authentication scheme here*/)

由于ASP.NET CoreAuthentication中间件只处理XSRF-TOKEN头,而不是X-XSRF-TOKENCookie,因此您不再容易受到跨站点请求伪造的影响。

剧透

您会注意到,在登录/注销之后,发送的第一个Web请求仍然会被XSRF保护阻止。这是因为身份在Web请求的生存期内不会更改。因此,当发送LoginWeb请求时,响应将附加一个带有CSRF令牌的cookie。但此令牌仍使用您尚未登录时的身份生成。

与发送LogoutWeb请求相同,响应将包含一个带有CSRF令牌的Cookie,就像您仍在登录一样。

要解决这个问题,您只需在每次登录/注销时发送另一个不做任何事情的Web请求。在此请求期间,您将再次拥有正确的身份以生成CSRF令牌。

logoutClicked() {
  this.accountService.logout().then(() => {
    this.accountService.csrfRefresh().then(() => {
      this.activeUser = null;
    });
  }).catch((error) => {
    console.error('Could not logout', error);
  });
}

登录相同

this.accountService.login(this.email, this.password).then((loginResult) => {
  this.accountService.csrfRefresh().then(() => {
    switch (loginResult.status) {
      case LoginStatus.success:
        this.router.navigateByUrl(this.returnUrl);
        this.loginComplete.next(loginResult.user);
        break;
      default:
        this.loginResult = loginResult;
        break;
    }
  });
});

csrfRefresh方法的内容

public csrfRefresh() {
  return this.httpClient.post(`${this.baseUrl}/web/Account/csrf-refresh`, {}).toPromise();
}

服务器端

[HttpPost("csrf-refresh")]
public async Task<ActionResult> RefreshCsrfToken()
{
    // Just an empty method that returns a new cookie with a new CSRF token.
    // Call this method when the user has signed in/out.
    await Task.Delay(5);

    return Ok();
}

This is where I login the user in my own app

这篇关于根据CSRF攻击,ASP.NET核心角度Web应用程序中的ValiateAntiForgeryToken终结点属性用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 06:10