Sisk

SiskでCORS(クロスオリジンリソース共有)を有効にする

このページは英語から自動翻訳されています。 原文を読む

Sisk には、サービスを公開する際に Cross-Origin Resource Sharing (CORS) の処理に役立つツールがあります。この機能は HTTP プロトコルの一部ではなく、W3C が定義した Web ブラウザ固有の機能です。このセキュリティ機構は、ウェブページがそのページを提供したドメインとは異なるドメインへリクエストを送ることを防止します。サービス提供者は特定のドメイン、あるいは単一のドメインに対してリソースへのアクセスを許可できます。

同一オリジン #

リソースが「同一オリジン」とみなされるためには、リクエストに Origin ヘッダーが含まれている必要があります:

HTTP
GET /api/users HTTP/1.1
Host: example.com
Origin: http://example.com
...

そして、リモートサーバーは要求されたオリジンと同じ値を持つ Access-Control-Allow-Origin ヘッダーで応答しなければなりません:

HTTP
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
...

この検証は 明示的 です。ホスト、ポート、プロトコルは要求されたものと同一である必要があります。例を確認してください:

  • サーバーが Access-Control-Allow-Origin を https://example.com と返す場合:
    • https://example.net - ドメインが異なる。
    • http://example.com - スキームが異なる。
    • http://example.com:5555 - ポートが異なる。
    • https://www.example.com - ホストが異なる。

仕様では、リクエストとレスポンスの両方のヘッダーに対して構文のみが許容されます。URL のパスは無視されます。ポートはデフォルトポート(HTTP は 80、HTTPS は 443)の場合は省略されます。

HTTP
Origin: null
Origin: <scheme>://<hostname>
Origin: <scheme>://<hostname>:<port>

CORS の有効化 #

標準で、ListeningHost 内に CrossOriginResourceSharingHeaders オブジェクトが用意されています。

サーバーの初期化時に CORS を設定できます:

C#
static async Task Main(string[] args)
{
    using var app = HttpServer.CreateBuilder()
        .UseCors(new CrossOriginResourceSharingHeaders(
            allowOrigin: "http://example.com",
            allowHeaders: ["Authorization"],
            exposeHeaders: ["Content-Type"]))
        .Build();

    await app.StartAsync();
}

上記のコードは すべてのレスポンス に対して以下のヘッダーを送信します:

HTTP
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Headers: Authorization
Access-Control-Expose-Headers: Content-Type

これらのヘッダーは、エラーやリダイレクトを含む、ウェブクライアントへのすべてのレスポンスで送信する必要があります。

CrossOriginResourceSharingHeaders クラスには、AllowOrigin と AllowOrigins の 2 つの類似したプロパティがあることに気付くでしょう。1 つは単数形、もう 1 つは複数形です。

  • AllowOrigin プロパティは静的です。指定したオリジンだけがすべてのレスポンスで送信されます。
  • AllowOrigins プロパティは動的です。サーバーはリクエストのオリジンがこのリストに含まれているかを確認し、含まれていればそのオリジンに対するレスポンスで送信されます。

許可されたオリジンがリクエストに依存する場合、つまり AllowOrigins や以下で説明する AutoAllowOrigin の値を使用する場合、Sisk は Vary: Origin ヘッダーも送信し、キャッシュが別のオリジン用のレスポンスを再利用しないようにします。

ワイルドカードと自動ヘッダー #

代わりに、レスポンスのオリジンにワイルドカード (*) を使用して、任意のオリジンからのリソースアクセスを許可することもできます。ただし、認証情報(認可ヘッダー)を含むリクエストに対してはこの値は使用できず、この操作は エラーになります。

この問題は、AllowOrigins プロパティで許可するオリジンを明示的に列挙するか、AllowOrigin の値に AutoAllowOrigin 定数を使用することで回避できます。このマジックプロパティは、リクエストの Origin ヘッダーと同じ値で Access-Control-Allow-Origin ヘッダーを設定します。

AllowOrigin と同様の動作で、送信されたヘッダーに基づいて自動的に応答するために、AutoFromRequestMethod と AutoFromRequestHeaders を使用することもできます。

C#
using var host = HttpServer.CreateBuilder()
    .UseCors(new CrossOriginResourceSharingHeaders(
        
        // リクエストの Origin ヘッダーに基づいて応答
        allowOrigin: CrossOriginResourceSharingHeaders.AutoAllowOrigin,
        
        // Access-Control-Request-Method ヘッダーまたはリクエストメソッドに基づいて応答
        allowMethods: [CrossOriginResourceSharingHeaders.AutoFromRequestMethod],

        // Access-Control-Request-Headers ヘッダーまたは送信されたヘッダーに基づいて応答
        allowHeaders: [CrossOriginResourceSharingHeaders.AutoFromRequestHeaders],

        exposeHeaders: [HttpKnownHeaderNames.ContentType, "X-Authenticated-Account-Id"],
        allowCredentials: true))
    .Build();

CORS を適用する他の方法 #

service providers を扱う場合、設定ファイルで定義された値を上書きできます:

C#
static async Task Main(string[] args)
{
    using var app = HttpServer.CreateBuilder()
        .UsePortableConfiguration(...)
        .UseCors(cors => {
            // 設定ファイルで定義されたオリジンを上書きします
            // file.
            cors.AllowOrigin = "http://example.com";
        })
        .Build();

    await app.StartAsync();
}

特定ルートでの CORS 無効化 #

UseCors プロパティはルートおよびすべてのルート属性で利用可能で、以下の例のように無効化できます:

C#
[RoutePrefix("api/widgets")]
public class WidgetController : Controller {

    // GET /api/widgets/colors
    [RouteGet("/colors", UseCors = false)]
    public IEnumerable<string> GetWidgets() {
        return new[] { "Green widget", "Red widget" };
    }
}

レスポンス内の値の置き換え #

ルーターアクション内で値を明示的に置き換えたり削除したりできます:

C#
[RoutePrefix("api/widgets")]
public class WidgetController : Controller {

    public IEnumerable<string> GetWidgets(HttpRequest request) {

        // Removes the Access-Control-Allow-Credentials header
        request.Context.OverrideHeaders.AccessControlAllowCredentials = string.Empty;
        
        // Replaces the Access-Control-Allow-Origin
        request.Context.OverrideHeaders.AccessControlAllowOrigin = "https://contorso.com";

        return new[] { "Green widget", "Red widget" };
    }
}

プリフライトリクエスト #

プリフライトリクエストとは、クライアントが実際のリクエストの前に送信する OPTIONS メソッドのリクエストです。

OPTIONS メソッドのリクエストがルートのパスと一致しても、OPTIONS 用に明示的にルートが設定されていない場合、Sisk サーバーは 200 OK と適用可能な CORS ヘッダーで応答し、その後クライアントは実際のリクエストを続行できます。

  • ルートが RouteMethod.Options(例: MapOptions)で明示的にマッピングされている場合、そのルートが自動応答ではなくリクエストを処理します。
  • パスに一致するルートに UseCors = false が設定されている場合でも、自動応答は送信されますが CORS ヘッダーは含まれません。

注記

Sisk 1.7 以前では、自動プリフライト応答は常に CORS ヘッダーを含んでおり、UseCors = false のルートでも同様でした。

グローバルに CORS を無効化する #

これは実現できません。CORS を使用しないようにするには、設定しないでください。

ドキュメントと API リファレンスを検索するには入力してください。