C#のASP.NETでCORSを設定する方法を完全解説!エラー解決とWebアプリ開発初心者向けガイド
生徒
「C#を使ってWebアプリを作っているのですが、画面のプログラムからデータを取得しようとすると、ブラウザの画面にコーズエラーという英語の赤い文字が出てデータが読み込めません。これは何が原因なのでしょうか?」
先生
「それは、Webアプリ開発で多くの人が最初に経験する壁ですね。そのエラーは、コーズと読み、セキュリティを守るための仕組みが働いている証拠です。C#のASP.NETという仕組みを使って、データの通信を許可する設定を追加することで解決できますよ。」
生徒
「セキュリティの仕組みなんですね。具体的にはどのようにC#のプログラムを書けば、その通信を許可することができるのですか?」
先生
「初心者の方でも順番に進めれば、驚くほど簡単に設定できます。それでは、基本的な仕組みから具体的なプログラムの書き方まで、一つずつ丁寧に見ていきましょう!」
1. CORSとは一体なに?初心者向けに徹底解説
プログラミングを始めたばかりの方にとって、英語の専門用語は難しく感じられますよね。まずは言葉の意味から順番に紐解いていきましょう。
コーズとは、日本語に直すと「オリジン間資源共有」という意味になります。これでもまだ難しいですね。もっと簡単に言うと、「別の場所にあるウェブサイト同士が、安全にデータをやり取りするための共通のルール」のことです。パソコンやスマートフォンでインターネットのページを見るとき、ブラウザという閲覧ソフトを使います。このブラウザには、悪意のあるプログラムからあなたのパソコンや個人情報を守るために、とても強力な防犯カメラと鍵が備わっています。
例えば、あなたが銀行のホームページを開いているとします。その状態で、別の怪しいお買い得情報サイトを開いたとしましょう。もしブラウザに防犯の仕組みがなければ、その怪しいサイトのプログラムが勝手に銀行のページにアクセスして、あなたのお金を勝手に操作できてしまう危険性があります。このような恐ろしい事態を防ぐために、ブラウザには「自分が今いる場所とは違う場所にあるデータは、基本的には勝手に読み込んではいけません」という非常に厳しい基本ルールが存在します。この防犯ルールを同源ポリシーと呼びます。
しかし、現代のWebアプリ開発では、デザインを表示する見た目のプログラムと、顧客データや商品を管理するC#で作った中身のプログラムを、あえて別のパソコンに分けて動かすことが一般的です。そのため、正常な開発であってもブラウザの防犯カメラが作動してしまい、「怪しい通信が行われようとしています」と通信を遮断してしまいます。これがエラーの正体です。この拒否反応を解除し、「このプログラムは安全な仲間だからデータを渡しても大丈夫だよ」と、C#で作ったWebアプリ側に許可証を持たせる設定が、今回のテーマとなります。
2. オリジンという言葉の意味を理解しよう
設定を進める前に、何度も登場する重要単語であるオリジンについて説明します。パソコンを触ったことがない方でも、インターネットのアドレスであるURLという言葉は聞いたことがあるかもしれません。URLは、インターネット上における情報の住所のようなものです。
オリジンとは、この住所の冒頭部分にある、次の3つの要素をセットにした仕組みのことを指します。
- 通信の種類(スキーム:主にエッチティーティーピーエスなど)
- コンピューターの名前(ドメイン:ウェブサイトの固有の名前)
- 接続する入り口の番号(ポート番号:通信を受け取る窓口の数字)
この3つのうち、どれか1つでも違っていれば、ブラウザは「全く別の場所である」と判断します。例えば、自分のパソコンの中で開発をしているとき、画面のプログラムが「ポート番号3000」で動いていて、C#のプログラムが「ポート番号5000」で動いているとします。同じパソコンの中で動かしているのに、数字が違うだけでブラウザは別世界のものと見なし、データの受け渡しを拒否します。私たちがこれから行う作業は、C#のプログラムに対して「ポート番号3000からのアクセスは安全だから許可する」というホワイトリストを登録する作業になります。
3. ASP.NETにおける設定の全体像と仕組み
C#でWebアプリを作る際、マイクロソフト社が提供しているASP.NETという便利な土台を使用します。最新のバージョンでは、プログラムの動きを管理する心臓部のようなファイルが存在します。そのファイルの名前は「Program.cs」といいます。このファイルは、Webアプリが起動した瞬間に上から順番に読み込まれる、案内図のような役割を持っています。
設定の流れは、大きく分けて2つの手順だけで完了します。パソコンの操作に慣れていなくても、この2つのステップを意識すれば迷うことはありません。
最初のステップは、サービスへの登録です。これは、Webアプリに対して「これから通信許可のルールを使うので、その準備をしてください」とあらかじめ教えてあげる作業です。ここでは、具体的にどの住所からのアクセスを許すのかという細かい設定内容を組み立てます。注文書を作るイメージを持つと分かりやすいでしょう。
次のステップは、ミドルウェアの適用です。これは、作った注文書を実際に稼働させる作業です。ASP.NETでは、外からのリクエストが届いたときに、様々なチェックを順番に行うパイプラインという通り道があります。その通り道に「通信許可のチェック係」を配置することで、実際に送られてきた通信を適切に処理できるようになります。それでは、実際のプログラムを見てみましょう。
4. 最もシンプルな全員許可の設定方法
まずは、一番手軽に動かすことができる、世界中の誰からでもアクセスを受け付ける最も簡単なプログラムを書いてみましょう。開発の初期段階で、まずは動くかどうかを確かめたいときに非常に便利な書き方です。Program.csの中に以下のように記述します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors("AllowAll");
app.MapGet("/data", () => new { Message = "成功しました" });
app.Run();
このプログラムについて詳しく解説します。まず最初の方にある「AddCors」という命令で、通信許可の準備を始めています。その中にある「AllowAnyOrigin」は、どこの住所から来ても拒否しないという意味です。「AllowAnyMethod」は、データの取得や書き込みなど、どんな種類の命令でも受け付けるという意味になります。最後の「AllowAnyHeader」は、通信の際に一緒に送られてくる付帯情報がどんな形であっても受け入れるという意味です。
そして、中盤にある「UseCors」という命令で、先ほど作った「AllowAll」という名前のルールを実際に有効化しています。この設定を行うだけで、先ほどブラウザで発生していた赤い文字のエラーは綺麗に消え去り、無事にデータを読み込むことができるようになります。ただし、この方法は誰にでも秘密のデータを公開してしまう状態なので、本物のアプリを世界に公開するときには使わないように注意しましょう。
5. 特定の相手だけを許可する安全な設定方法
全員に公開する方法は危険が伴うため、実務の開発や本番環境では、特定の信頼できる相手だけを許可する設定を行います。例えば、自分の画面プログラムが動いている特定の住所だけを限定して鍵を開ける方法です。
特定の住所を指定する場合は、先ほどのプログラムを少し書き換えます。以下のコードブロックを確認してください。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowMyFrontend", policy =>
{
policy.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors("AllowMyFrontend");
app.Run();
今回のプログラムでは、「WithOrigins」という新しい言葉が使われています。この括弧の中に、自分が許可したい正確な住所を文字として書き込みます。ここでは、開発中によく使われる「http://localhost:3000」という住所を指定しています。
このように設定することで、この特定の住所から届いた通信だけが合格となり、それ以外の全く関係のない見知らぬ場所から届いた不正なアクセスは、ブラウザとC#の強力な連携によって完全にシャットアウトされます。非常に安全で、現代のWeb開発で最も推奨される基本の形です。文字列の最後にスラッシュなどの余計な文字を入れないように書くのが、失敗しないための大切なコツです。
6. 複数の特定の住所をまとめて許可する方法
実際の開発が進んでいくと、自分自身のパソコンだけでなく、テストを行うための別のパソコンや、本番環境として公開されたインターネット上のサーバーなど、複数の場所からの通信を同時に許可したい場面が出てきます。そのような場合にも、C#のプログラムは柔軟に対応することができます。
複数の住所を登録する場合は、カンマという記号で区切って並べることで、まとめてホワイトリストに登録することができます。実際の書き方を見てみましょう。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowMultipleSites", policy =>
{
policy.WithOrigins("http://localhost:3000", "https://www.example.com")
.WithMethods("GET", "POST")
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors("AllowMultipleSites");
app.Run();
この例では、「WithOrigins」の中に、開発用の住所と、本番用をイメージした「https://www.example.com」という2つの住所を同時に指定しています。これによって、どちらの場所からアクセスが来ても、C#のアプリは優しく受け入れてくれます。
さらに、今回は「WithMethods」という命令を使って、データの取得を意味するゲットと、データの送信を意味するポストという2つの操作だけに役割を限定しています。これにより、データを勝手に削除されるような危険な操作をあらかじめ禁止することができ、Webアプリの防犯レベルをさらに一段階引き上げることができます。
7. 特定のコントローラーだけ個別に制御する方法
ここまでは、Webアプリ全体に一括でルールを適用する方法を解説してきましたが、ASP.NETでは、特定の機能の窓口ごとに個別のルールを設定することも可能です。これをコントローラー単位での制御と呼びます。
全体への適用は緩やかにしておき、個人情報を扱う重要な窓口だけを厳格に制限したい場合などにこの方法が選ばれます。プログラムの書き方を確認しましょう。
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace MyWebApi.Controllers;
[ApiController]
[Route("api/[controller]")]
[EnableCors("AllowMyFrontend")]
public class UserController : ControllerBase
{
[HttpGet]
public IActionResult GetUser()
{
return Ok(new { Name = "山田太郎" });
}
}
このプログラムでは、クラスと呼ばれる命令の塊のすぐ上の部分に、「[EnableCors("AllowMyFrontend")]」という特殊な記述を追加しています。これは属性と呼ばれる機能で、この窓口に対して名指しでルールを指定する役割を持っています。
この記述があることで、Program.csで事前に定義しておいた特定のルールが、この UserController という窓口だけにピンポイントで適用されます。アプリ全体の仕組みを複雑にすることなく、特定の機能だけをカスタマイズできるため、中規模以上の本格的なシステム開発で大いに活躍する記述方法です。
8. 初心者が最も陥りやすい注意点と解決策
最後に、プログラミングを始めたばかりの方が最も間違えやすい落とし穴について解説します。C#のプログラムは、上に書かれた行から順番に実行されるという大原則があります。そのため、命令を書く順番が1行でも前後すると、全く動かなくなってしまうことがあります。
特に注意が必要なのが、「UseCors」を書く位置です。ASP.NETには、ルートという通信の行き先を決める仕組みや、認証という本人確認を行う仕組みなど、多くのチェック係が並んでいます。この並び順を間違えると、せっかく書いた通信許可の設定が無視されてしまいます。失敗する典型的な順番と、正しい順番を比較してみましょう。
正しく動かない順番の例は以下の通りです。
app.UseRouting();
app.MapControllers();
app.UseCors("AllowMyFrontend"); // これでは位置が遅すぎてエラーになります
正しく動作する完璧な順番の例は以下の通りです。
app.UseRouting();
app.UseCors("AllowMyFrontend"); // 行き先が決まったら、最初に許可チェックを行います
app.MapControllers();
このように、「UseRouting」のすぐ後ろ、そして実際の処理を行う窓口である「MapControllers」や「MapGet」よりも必ず前に「UseCors」を記述してください。この位置関係さえしっかりと守っていれば、設定が反映されずに頭を抱える心配はありません。パソコンの操作に不慣れな方でも、この順番のルールを意識するだけで、プロのエンジニアと同じように綺麗な通信処理を実装することができます。