クロスサイト要求偽造を無効にする - Razor Pages

RazorPagesでの「クロスサイト偽造要求」(Antiforgery) を無効にするコードを紹介します。

概要

RazorPagesでは、クロスサイト要求偽造 (XSRF/CSRF) 攻撃を防ぐためのトークン検証の仕組みがデフォルトで有効になっています。
セキュリティ対策面では有効な仕組みであり、通常は無効にする必要はありません。しかし、Webフォームでの編集時間が非常に長い場合、 すなわち、ページの表示からPOSTされるまでの時間が長時間になる場合、 トークン検証でエラーが発生しポスト時にHTTP 500エラーが稀に発生する場合があります。 頻度が低いため通常のWebフォームでは問題にならないですが、フォームのPOST時に極力エラーを発生させたくない場合は、クロスサイト要求偽造を無効にして、 エラーの発生を回避できます。

この記事ではクロスサイト要求偽造の処理を無効にするコードを紹介します。

手順

補足
1:asp-antiforgery="false" と 2:IgnoreAntiforgeryToken 属性の追加、両方を実施する必要があります。
片方だけの修正では、POST時にHTTP 400エラーが発生し正しく動作しません。

1:RazorPagesのフォームタグに asp-antiforgery="false" を記述する

RazorePagesのフォームタグに asp-antiforgery="false" 属性を記述します。

記述例

  <form method="post" asp-antiforgery="false">
    <!-- 中略 -->
  </form>

2:ページモデルクラスに IgnoreAntiforgeryToken 属性を記述する

RazorPagesのページモデルクラスに [IgnoreAntiforgeryToken] 属性を記述します。

記述例

namespace ExampleProject.Pages
{
  [IgnoreAntiforgeryToken]
  public class FormModel : PageModel
  {
    <!-- 中略 -->
  }
}

プログラム例

ASP.NET Core Webアプリケーションプロジェクトを作成します。

コード

下記のコードを記述します。
Pages/Form.cshtml
@page
@model IgnoreAntiforgery.Pages.FormModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
  Layout = null;
}

<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Form</title>

</head>
<body>
  <p>クロスサイト要求偽造を無効にするデモ</p>
  @{
    if (Model.IsPost==true){
      <p>ポストされました</p>
      <p>ポストされた値:@Model.TextBoxValue</p>
    }
  }
  <form method="post" asp-antiforgery="false">
    <input type="text" asp-for="TextBoxValue"/>
    <input type="submit" value="POST" />
  </form>
</body>
</html>
Pages/Form.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace IgnoreAntiforgery.Pages
{
  [IgnoreAntiforgeryToken]
  public class FormModel : PageModel
  {
    [BindProperty]
    public string TextBoxValue{ get; set; }

    public bool IsPost { get; set; }

    public void OnGet()
    {
      IsPost = false;
    }

    public void OnPost()
    {
      IsPost = true;
    }
  }
}
startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace IgnoreAntiforgery
{
  public class Startup
  {
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
      services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
      }


      app.UseRouting();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapRazorPages();
      });
    }
  }
}

解説

Formタグに asp-antiforgery="false" を記述します。
 <form method="post" asp-antiforgery="false">

ページモデルのクラス宣言部分に [IgnoreAntiforgeryToken] 属性を指定します。
  [IgnoreAntiforgeryToken]
  public class FormModel : PageModel

実行結果

プロジェクトを実行します。下図のページが表示されます。


テキストボックスに文字列を入力し、[POST]ボタンをクリックします。


フォームの内容がポストされ、ポストされた内容がページに表示されます。POSTの動作が正しく実行されていることが確認できます。

参考 : 出力されるHTMLの違い

出力されるHTMLを確認します。
Antiforgery が有効な場合はhidden属性の__RequestVerificationTokenフィールドが追加されていることが確認できます。
Antiforgery が有効な場合
<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Form</title>

</head>
<body>
  <p>クロスサイト要求偽造を無効にするデモ</p>
  <form method="post">
    <input type="text" id="TextBoxValue" name="TextBoxValue" value="" />
    <input type="submit" value="POST" />
  <input name="__RequestVerificationToken" type="hidden" 
value="CfDJ8Kcy693ModNFl4aCANCbqN3XfnUNZxpan6v2scEc66FWEl7Bq8vfrczwN_NdRPxRPmUjk60CXkSJVJ958cScidXUOQhgmCGJTvzAYguBDCHVRBM6wgMT6lqGSCVmDcXevhzMTIAA8B_Ve-O_XNAeUZc" /></form>
</body>
</html>
Antiforgery を無効にした場合
<!DOCTYPE html>

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Form</title>

</head>
<body>
  <p>クロスサイト要求偽造を無効にするデモ</p>
  <form method="post" action="/Form">
    <input type="text" id="TextBoxValue" name="TextBoxValue" value="" />
    <input type="submit" value="POST" />
  </form>
</body>
</html>
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-06-16
作成日: 2020-04-10
iPentec all rights reserverd.