1. 導入
現代のWebアプリケーション開発において、画面遷移を伴わずにサーバーと動的にデータをやり取りする「Ajax(非同期通信)」は必須の技術です。しかし、PHPでAPIを構築する際、セキュリティの考慮やドメイン間通信(クロスドメイン)の制御で躓くエンジニアは少なくありません。本稿では、PHPバックエンドの視点から、安全かつ効率的なAjax通信の実装方法と、現場で必須となるCORS(Cross-Origin Resource Sharing)の考え方を解説します。
2. 基礎知識
Ajax通信を行う際、バックエンド側で意識すべき重要な仕組みがいくつかあります。
HTTPヘッダーの活用
サーバー側で「このリクエストはAjaxによるものか?」を判別するために、`X-Requested-With` ヘッダーを確認するのが一般的です。また、ブラウザのセキュリティ機能である「同一生成元ポリシー(Same-Origin Policy)」により、異なるドメイン間での通信は制限されます。これを解決するために、サーバー側で許可設定(CORS)を行う必要があります。
3. 実装/解決策
実務では、単にデータを返すだけでなく、リクエストの妥当性チェックと、適切なレスポンスヘッダーの付与が重要です。
セキュリティ対策のポイント
1. HTTP_X_REQUESTED_WITHの確認: ブラウザからの直接アクセスを弾き、Ajaxリクエストのみを受け付けます。
2. CORSの設定: 外部ドメインからのアクセスを許可する場合は、`Access-Control-Allow-Origin` ヘッダーを適切に設定します。※「」は認証が必要なリクエストでは使用できないため注意してください。
4. サンプルプログラム
以下は、フロントエンドから受け取ったデータを処理し、JSON形式で安全に返す実用的なPHPのサンプルコードです。
/
// 1. Ajaxリクエスト以外からのアクセスを拒否
$request = isset($_SERVER[‘HTTP_X_REQUESTED_WITH’])
? strtolower($_SERVER[‘HTTP_X_REQUESTED_WITH’]) : ”;
if ($request !== ‘xmlhttprequest’) {
http_response_code(403);
exit(‘Forbidden’);
}
// 2. CORSの許可設定(必要に応じて特定のドメインのみ許可すること)
header(“Access-Control-Allow-Origin: https://example.com”);
header(“Access-Control-Allow-Methods: POST, GET, OPTIONS”);
header(“Content-type: application/json; charset=utf-8”);
// 3. 入力値のバリデーション
$text = filter_input(INPUT_POST, ‘text’, FILTER_SANITIZE_SPECIAL_CHARS);
if (!$text) {
echo json_encode([‘status’ => ‘error’, ‘message’ => ‘無効なデータです’]);
exit;
}
// 4. 処理結果をJSONで出力
$result = [
‘status’ => ‘success’,
‘received’ => $text,
‘message’ => ‘データを受信しました’,
‘timestamp’ => date(‘Y-m-d H:i:s’)
];
echo json_encode($result);
?>
5. 応用・注意点
現場で遭遇しやすいトラブルと対策をまとめます。
・JSONPは避ける
かつてクロスドメイン通信の定番だった「JSONP」は、セキュリティ上のリスク(XSSのリスク)が高いため、現代の開発では推奨されません。必ず CORS(Cross-Origin Resource Sharing) を使用してください。
・プリフライトリクエストへの対応
`POST` メソッドやカスタムヘッダーを送信する場合、ブラウザは本番通信の前に `OPTIONS` メソッドで事前確認(プリフライト)を行います。PHP側で `OPTIONS` リクエストに対して適切なヘッダー(Allow-OriginやAllow-Headers)を返さないと、通信がブロックされるので注意してください。
・負荷対策
サンプルのようなファイルベースのログ読み込みは、アクセス数が増えるとファイルロック待ちで遅延が発生します。実務ではRedisやデータベース(MySQL等)を使用し、適切にキャッシュを活用する構成を目指しましょう。