| Flex Gateway ポリシー開発キット (PDK) のクロスオリジンリソース共有 (CORS) ライブラリを使用したポリシープロジェクトの例は、 「CORS Validation Policy Example (CORS 検証ポリシーの例)」を参照してください。 |
CORS は、Web アプリケーションが別のドメインで定義されたリソースにアクセスするためのメカニズムです。ブラウザーでは、デフォルトで CORS がサポートされています。PDK CORS ライブラリは、 CORS W3C 勧告の標準に準拠しており、受信要求を検証してリソースを保護する一連のツールが用意されています。
CORS 設定インスタンスを定義する
CORS ライブラリは、pdk::cors モジュールから使用できます。このモジュールでは、受信要求の検証メソッドを定義するための cors::Configuration、cors::OriginGroup、cors::AllowedMethod 構造とそれらのビルダーが提供されます。たとえば、次のコードスニペットでは、cors::Configuration インスタンスをハードコード化する関数を定義します。
use pdk::cors;
fn create_cors_configuration() -> cors:Configuration {
cors::Configuration::builder()
.public_resource(false)
.support_credentials(true)
.origin_groups(vec![cors::OriginGroup::builder()
.origin_group_name("default group".to_string())
.plain_origins(vec!["http://www.the-origin-of-time.com".to_string()])
.access_control_max_age(60)
.headers(vec![
"x-allow-origin".to_string(),
"x-yet-another-valid-header".to_string(),
])
.exposed_headers(vec!["x-forwarded-for".to_string()])
.allowed_methods(vec![
cors::AllowedMethod::builder()
.method_name("POST".to_string())
.allowed(true)
.build()
.unwrap(),
cors::AllowedMethod::builder()
.method_name("PUT".to_string())
.allowed(true)
.build()
.unwrap(),
])
.build()
.unwrap()])
.build()
.unwrap();
}
cors::Configuration 構造の設定パラメーター
| プロパティ | 必須または省略可能 | デフォルト値 | 説明 |
|---|---|---|---|
|
省略可能 |
空の |
|
|
省略可能 |
|
CORS 設定が公開リソースとして適用されるかどうかを示すブール値。 |
|
省略可能 |
|
CORS 設定が Cookie、認証ヘッダー、TLS クライアント証明書などのログイン情報をサポートするかどうかを示すブール値。 |
cors::OriginGroup 構造の設定パラメーター
| プロパティ | 必須または省略可能 | デフォルト値 | 説明 |
|---|---|---|---|
|
省略可能 |
空の |
グループに含まれるオリジンの |
|
省略可能 |
30 |
新しいプレフライト要求を送信する前にプレフライト応答をキャッシュする期間 (秒)。 |
|
省略可能 |
空の |
|
|
省略可能 |
空の |
プレフライト要求の HTTP ヘッダーの |
|
省略可能 |
空の |
ブラウザーの JavaScript でアクセスできるヘッダーの |
CORS 検証メソッド
cors::Cors 構造には、指定された cors::Configuration インスタンスに対して受信ヘッダーを検証する check_headers() メソッドが含まれます。cors::Cors::check_headers() メソッドは、Result<cors::Check, cors::CorsError> 構造を返します。CORS 検証に失敗した場合の結果は Err になります。検証に通過すると、要求は Ok になり、cors::Check 構造を評価できます。
cors::Check 構造の使用可能なメソッド
| メソッド | 種別 | 説明 |
|---|---|---|
|
|
受信要求に必要なアクションの種別が含まれる列挙を返します。列挙値についての詳細は、 |
|
|
応答に追加するヘッダーのリスト。 |
|
|
|
CORS 検証ポリシーを記述する
CORS 検証ポリシーを記述する手順は、次のとおりです。
-
cors::Configuration インスタンスを定義する #[entrypoint] 関数を定義します。次の例の create_cors_configuration() は、CORS 設定インスタンスを定義するの例で定義された関数です。use pdk::*; use pdk::cors; #[entrypoint] async fn configure(launcher: Launcher) -> Result<(), LaunchError> { let cors_configuration = create_cors_configuration(); let filter = on_request(|rs| request_filter(rs, &cors_configuration)) .on_response(response_filter); launcher.launch(filter).await } -
CORS 検証メソッドを使用して受信要求を検証する
request_filter() 関数を定義します。返されるフローには、cors::Cors::check_headers() から返されたヘッダーを response_filter() に渡す Vec<(String, String)> が含まれている必要があります。async fn request_filter( request_headers_state: RequestHeadersState, cors_configuration: &cors::Configuration<'_>, ) -> Flow<Vec<(String, String)>> { // Create a new CORS checker. let cors = cors::Cors::new(cors_configuration); let request_headers = request_headers_state.handler().headers(); let cors_result = cors.check(&request_headers); match cors_result { // The CORS validation was succesful. Ok(cors_check) => match cors_check.response_type() { // A CORS preflight fetch was requested, return an early response. cors::ResponseType::Preflight => { Flow::Break(Response::new(200).with_headers(check.into_headers())) } // This is a CORS main request, continue and pass the headers to the response. cors::ResponseType::Main => { logger::info!("Main CORS response."); Flow::Continue(check.into_headers()) } }, // The CORS validation failed. The request must be refused. Err(cors_error) => { Flow::Break(Response::new(200)) } } } -
CORS 検証メソッドを使用して応答を検証する
response_filter() 関数を定義します。RequestData には、cors::Cors::check_headers() で返されるヘッダーが含まれます。async fn response_filter(state: ResponseHeadersState, data: RequestData<Vec<(String, String)>>) { // Take the headers to add from the request data. let RequestData::Continue(headers_to_add) = data else { return; }; // Add the headers to the response for (name, value) in headers_to_add.iter() { state.handler().set_header(name, value); } }