You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor独立账户认证下内部API的CSRF防护问询

Blazor WebApp(独立账户认证 + .NET 8)的内部API CSRF防护问题

我通过Blazor WebApp模板创建了一个自动渲染(Interactive Auto)且启用独立账户认证的.NET 8项目。

服务端新增了一个带[Authorize]特性的内部API控制器,包含POST方法;客户端通过Razor页面(带[Authorize],自动渲染模式)使用HttpClient调用该API的POST接口。

我想确认:这类项目会自动为内部API提供CSRF防护吗?还是需要额外配置来保障安全?


服务端代码:TestController.cs

namespace WebAppAutoIndividual.Controllers
{
    [ApiController]
    [Route("api/test2")]
    [Authorize]
    public class Test2Controller : Controller
    {

        private readonly ITest2Service _service;

        public Test2Controller(ITest2Service service)
        {
            _service = service ?? throw new ArgumentNullException(nameof(service));
        }

        [HttpGet]
        public DataTest[] Read()
        {
            var items = _service.Get().Result;

            return items;
        }

        [HttpPost]
        public void Create([FromBody] DataTest dto)
        {
            _service.Add(dto);
        }

    }
}

客户端Razor页面:form-auto-controller.razor

@page "/form-auto-controller"
@attribute [Authorize]
@rendermode InteractiveAuto

@using System.ComponentModel.DataAnnotations
@using System.Net.Http
@using WebAppAutoIndividual.Client.Services

@inject ILogger<FormAutoController> Logger
@inject ITest2Service Service

<PageTitle>Formulaire avec Controleur avec rendu auto</PageTitle>

<p>Mode de rendu : @(OperatingSystem.IsBrowser() ? "Wasm" : "Server")</p>

<EditForm Model="Model" OnValidSubmit="SubmitAsync" FormName="StarshipClientAutoRender">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <label>
        Prénom :
        <InputText @bind-Value="Model!.FirstName" />
    </label>
    <label>
        Nom :
        <InputText @bind-Value="Model!.Name" />
    </label>
    <button type="submit">Submit</button>
</EditForm>

@if (allModels == null)
{
    <p>Loading ...</p>
}
else
{
    <label> je suis @serviceName</label>
    <button @onclick="Refresh">Refresh</button>

    @foreach(DataTest i in allModels)
    {
        <p>@i.Name, @i.FirstName</p>
    }

}

@code {
    [SupplyParameterFromForm]
    public DataTest? Model { get; set; }
    private DataTest[] allModels { get; set; } = null;
    private DateTime DateTimeRefresh = DateTime.Now;
    private string serviceName = "aucun";

    protected override async Task OnInitializedAsync()
    {
        Model ??= new();
        serviceName = Service.Whois();
        allModels = await Service.Get();
    }

    protected async Task Refresh()
    {
        allModels = await Service.Get();
        DateTimeRefresh = DateTime.Now;
    }

    private async Task SubmitAsync()
    {
        Logger.LogInformation("Prénom Nom = {fisrtname} {name}", Model?.FirstName, Model?.Name);

        if (Model != null)
        {
            await Service.Add(Model);
        }
    }

}

客户端Http服务:Test2ProxyService.cs

namespace WebAppAutoIndividual.Client.Services;

public class Test2ProxyService : ITest2Service
{
    private readonly HttpClient _http;
    public Test2ProxyService(HttpClient http) { 
        _http = http;
    }

    public string Whois() { return nameof(Test2ProxyService); }

    public async Task Add(DataTest test)
    {
        Console.WriteLine("Service 2 POST depuis le client");
        await _http.PostAsJsonAsync("/api/test2", test);
    }

    public async Task<DataTest[]> Get()
    {
        Console.WriteLine("Service 2 GET test depuis le client");
        var result = await _http.GetFromJsonAsync<DataTest[]>("/api/test2");
        return result;
    }
}

回答

针对你的场景,分两种运行模式说明CSRF防护情况:

1. Interactive Server模式运行时

此时Blazor Server会自动处理CSRF防护:

  • 框架自动生成并验证XSRF-TOKEN Cookie和RequestVerificationToken请求头
  • 注入的HttpClient会自动携带这些令牌,无需额外配置
  • 你的API控制器继承了Controller,默认会验证POST/PUT/DELETE等非安全请求的CSRF令牌,当前代码已具备防护能力

2. Interactive WebAssembly模式运行时

Wasm模式下的CSRF防护需要额外配置:

  • 独立账户认证体系不会自动为Wasm客户端的API请求添加CSRF令牌
  • 需手动配置并实现令牌的获取与携带:
    1. 在服务端Program.cs中配置CSRF服务:
      builder.Services.AddAntiforgery(options =>
      {
          options.HeaderName = "X-XSRF-TOKEN";
          options.Cookie.Name = "XSRF-TOKEN";
          options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境建议启用
      });
      
    2. 在API控制器的POST方法上添加[ValidateAntiForgeryToken]特性(或全局配置验证):
      [HttpPost]
      [ValidateAntiForgeryToken]
      public void Create([FromBody] DataTest dto)
      {
          _service.Add(dto);
      }
      
    3. 在Wasm客户端的Http服务中先获取CSRF令牌,再发起请求:
      public async Task Add(DataTest test)
      {
          // 获取CSRF令牌
          var tokenResponse = await _http.GetAsync("/api/antiforgery/token");
          tokenResponse.EnsureSuccessStatusCode();
          var token = await tokenResponse.ReadFromJsonAsync<AntiforgeryTokenResponse>();
          
          // 添加令牌到请求头
          _http.DefaultRequestHeaders.Add("X-XSRF-TOKEN", token.RequestToken);
          
          Console.WriteLine("Service 2 POST depuis le client");
          await _http.PostAsJsonAsync("/api/test2", test);
      }
      
      同时在服务端新增获取令牌的API端点:
      [ApiController]
      [Route("api/antiforgery")]
      public class AntiforgeryController : Controller
      {
          private readonly IAntiforgery _antiforgery;
          public AntiforgeryController(IAntiforgery antiforgery)
          {
              _antiforgery = antiforgery;
          }
      
          [HttpGet("token")]
          public IActionResult GetToken()
          {
              var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
              return Ok(new { RequestToken = tokens.RequestToken });
          }
      }
      

3. Interactive Auto模式的注意事项

Auto模式会根据场景切换Server/Wasm模式,需同时兼容两种配置:

  • 保留Server模式的自动防护逻辑
  • 添加Wasm模式所需的CSRF配置与令牌获取代码
  • 可通过OperatingSystem.IsBrowser()判断运行环境,区分处理逻辑

内容的提问来源于stack exchange,提问作者Sébastien Foucher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:21:11