単純なプロキシ実装例

提供: svg2wiki
(版間での差分)
移動: 案内, 検索
(svgMap.jsの初期化)
(ソースコード)
 
(1人の利用者による、間の13版が非表示)
1行: 1行:
この例は、かなり単純なCORSプロキシの実装例です。よりセキュリティに配慮した実装が必要なケースがありますので、[[クロスオリジンアクセス]]の他の実装を参照の上利用を検討してください。
+
この例は、PHPによる かなり単純なCORSプロキシの実装例です。よりセキュリティに配慮した実装が必要なケースがありますので、[[クロスオリジンアクセス]]の他の実装を参照の上利用を検討してください。
  
  
8行: 8行:
 
<html>
 
<html>
 
...
 
...
<script src="corsProxy.js"></script> <!-- クロスオリジンアクセス用プロキシライブラリ(下記) -->
+
<script type="module">
<script src="SVGMapLv0.1_r17.js"></script>
+
import { CorsProxy } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/CorsProxyModule.js';
...
+
import { svgMap } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/SVGMapLv0.1_r18module.js';
<script>
+
window.svgMap=svgMap
var proxyPath = "simpleCORSproxy.php"; // CORS anywhere for svgmap.org / service.svgmap.org
+
var corsProxy = new CorsProxy();
corsProxy.setService(proxyPath, null, true, true);
+
 
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURL,true);
+
// プロキシの設定
 +
var proxyPath = "https://..url..of../simpleCORSproxy.php?file=";
 +
 
 +
corsProxy.setService(proxyPath, null, true, true); // 第4パラメータをtrueにするとアクセス先URLをエンコードする
 +
window.corsProxy = corsProxy;
 +
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURLfunction(), true); // ビットイメージ非線形図法変換の時のみプロキシを使う
 
</script>
 
</script>
 
...
 
...
23行: 28行:
 
* corsProxy.jsは[[クロスオリジンアクセス#corsProxy.js]]を参照
 
* corsProxy.jsは[[クロスオリジンアクセス#corsProxy.js]]を参照
 
* <code>corsProxy.setService</code>の、requireEncoding フラグはtrueにします。
 
* <code>corsProxy.setService</code>の、requireEncoding フラグはtrueにします。
 +
** 本php実装ではfileクエリに記載される取得先URLがURLエンコードされていることを想定しているため
  
 
== ソースコード ==
 
== ソースコード ==
 
* simpleCORSproxy.php
 
* simpleCORSproxy.php
* <code>if (preg_match("|^https?://svgmap\.org|", $referer) .. </code>の行を適宜書き換えてください
+
* proxyへのアクセスに際して、refererリクエストヘッダが必要なコードになっています。
 +
<!-- * refererヘッダを用いてアクセス制限をかける場合、プロキシはwebAppと別ドメインになっている必要があります。(同一ドメインではrefererヘッダが付与されない)
 +
** 参考までに、同じホストでもwww.[ドメイン名]と[ドメイン名]が別ドメインとして認識されることを利用することもできます。
 +
** refererヘッダによる制限のためには、<code>if (preg_match("|^https?://svgmap\.org|", $referer) .. </code>の行を適宜書き換えてください-->
 
<code>
 
<code>
 
<pre>
 
<pre>
 
<?php
 
<?php
function file_get_contents_curl($url) {
+
 
$headers = array(
+
// 許可するリファラードメインの正規表現リスト
    "HTTP/1.0",
+
// 必要に応じてここにドメインを編集・追加してください。
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
+
$allowedReferers = [
//     "Accept-Encoding:gzip ,deflate",
+
    '#^https?://www\.svgmap\.org/#',
    "Accept-Language:ja,en-us;q=0.7,en;q=0.3",
+
    // '#^https?://example\.com/#',
    "Connection:keep-alive",
+
];
    "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
+
 
    );
+
if (isset($_GET['file'])) {
     // **/
+
    $fileUrl = urldecode($_GET['file']);
 +
    $referer = $_SERVER['HTTP_REFERER'] ?? '';
 +
 
 +
    // 許可されたリファラーからのアクセスかチェック
 +
     $isAllowed = false;
 +
    foreach ($allowedReferers as $pattern) {
 +
        if (preg_match($pattern, $referer)) {
 +
            $isAllowed = true;
 +
            break;
 +
        }
 +
    }
 +
 
 +
    // リファラーが無効な場合はアクセスを拒否
 +
    if (!$isAllowed) {
 +
        header("HTTP/1.1 403 Forbidden");
 +
        echo "Error: Access denied. Invalid or missing Referer.";
 +
        exit();
 +
    }
 +
 
 +
     // cURLセッションの初期化と設定
 
     $ch = curl_init();
 
     $ch = curl_init();
 +
    curl_setopt_array($ch, [
 +
        CURLOPT_RETURNTRANSFER => 1,
 +
        CURLOPT_URL => $fileUrl,
 +
        CURLOPT_FOLLOWLOCATION => true,
 +
        CURLOPT_TIMEOUT => 30,
 +
        CURLOPT_CONNECTTIMEOUT => 10,
 +
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
 +
    ]);
  
     curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
+
     $contentData = curl_exec($ch);
    curl_setopt($ch, CURLOPT_HEADER, 0);
+
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
    curl_setopt($ch, CURLOPT_URL, $url);
+
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);     
+
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);      
+
  
     $data = curl_exec($ch);
+
     if ($contentData === false) {
    curl_close($ch);
+
        header("HTTP/1.1 500 Internal Server Error");
 +
        echo "Error: Could not retrieve content.";
 +
        exit();
 +
    }
  
     return $data;
+
     // MIMEタイプを自動で判定して設定
}
+
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
 +
    $contentType = finfo_buffer($finfo, $contentData);
 +
    finfo_close($finfo);
 +
 
 +
    // テキスト系ファイルの場合はUTF-8を指定
 +
    if (strpos($contentType, 'text/') === 0 || $contentType === 'application/json') {
 +
        header("Content-Type: " . $contentType . "; charset=UTF-8");
 +
    } else {
 +
        header("Content-Type: " . $contentType);
 +
    }
 +
   
 +
    echo $contentData;
 +
    curl_close($ch);
  
if($_GET["file"]){
 
 
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
 
// accept only referrer within this site
 
header("Access-Control-Allow-Origin: " . "*"); // MUST SET for CORS
 
if (preg_match("|^https?://svgmap\.org|", $referer) || preg_match("|^https?://www\.svgmap\.org|", $referer)) {
 
if ( $_GET["type"]){
 
header("Content-type: " . $_GET["type"]);
 
} else {
 
if(strpos($_GET["file"],'png')){
 
header("Content-type: image/png");
 
} else {
 
header("Content-Type:image/jpeg;");
 
}
 
}
 
echo file_get_contents_curl( urldecode($_GET["file"]), true);
 
} else {
 
echo "ERR : referer : " .  $referer;
 
}
 
 
} else {
 
} else {
foreach (getallheaders() as $name => $value) {
+
    header("Content-Type: text/html; charset=UTF-8");
echo "$name: $value<br>";
+
    echo "<h1>Content Proxy</h1><p>This proxy requires a 'file' GET parameter with a URL-encoded content URL.</p>";
}
+
foreach ($_GET as $key => $value) {
+
echo "GET Key:".$key.",  Value:".$value."<br>";
+
}
+
echo "referrer: ".$_SERVER['HTTP_REFERER'];
+
 
}
 
}
?>
 
 
</pre>
 
</pre>
 
</code>
 
</code>

2025年8月12日 (火) 02:46時点における最新版

この例は、PHPによる かなり単純なCORSプロキシの実装例です。よりセキュリティに配慮した実装が必要なケースがありますので、クロスオリジンアクセスの他の実装を参照の上利用を検討してください。


[編集] svgMap.jsの初期化

<!doctype html>
<html>
...
<script type="module">
import { CorsProxy } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/CorsProxyModule.js';
import { svgMap } from 'https://cdn.jsdelivr.net/gh/svgmap/svgmapjs@latest/SVGMapLv0.1_r18module.js';
window.svgMap=svgMap
var corsProxy = new CorsProxy();

// プロキシの設定
var proxyPath = "https://..url..of../simpleCORSproxy.php?file=";

corsProxy.setService(proxyPath, null, true, true); // 第4パラメータをtrueにするとアクセス先URLをエンコードする
window.corsProxy = corsProxy;
svgMap.setProxyURLFactory(null,null,null, corsProxy.getURLfunction(), true); // ビットイメージ非線形図法変換の時のみプロキシを使う
</script>
...
</html>

  • corsProxy.jsはクロスオリジンアクセス#corsProxy.jsを参照
  • corsProxy.setServiceの、requireEncoding フラグはtrueにします。
    • 本php実装ではfileクエリに記載される取得先URLがURLエンコードされていることを想定しているため

[編集] ソースコード

  • simpleCORSproxy.php
  • proxyへのアクセスに際して、refererリクエストヘッダが必要なコードになっています。

<?php

// 許可するリファラードメインの正規表現リスト
// 必要に応じてここにドメインを編集・追加してください。
$allowedReferers = [
    '#^https?://www\.svgmap\.org/#',
    // '#^https?://example\.com/#',
];

if (isset($_GET['file'])) {
    $fileUrl = urldecode($_GET['file']);
    $referer = $_SERVER['HTTP_REFERER'] ?? '';

    // 許可されたリファラーからのアクセスかチェック
    $isAllowed = false;
    foreach ($allowedReferers as $pattern) {
        if (preg_match($pattern, $referer)) {
            $isAllowed = true;
            break;
        }
    }

    // リファラーが無効な場合はアクセスを拒否
    if (!$isAllowed) {
        header("HTTP/1.1 403 Forbidden");
        echo "Error: Access denied. Invalid or missing Referer.";
        exit();
    }

    // cURLセッションの初期化と設定
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_URL => $fileUrl,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    ]);

    $contentData = curl_exec($ch);

    if ($contentData === false) {
        header("HTTP/1.1 500 Internal Server Error");
        echo "Error: Could not retrieve content.";
        exit();
    }

    // MIMEタイプを自動で判定して設定
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $contentType = finfo_buffer($finfo, $contentData);
    finfo_close($finfo);

    // テキスト系ファイルの場合はUTF-8を指定
    if (strpos($contentType, 'text/') === 0 || $contentType === 'application/json') {
        header("Content-Type: " . $contentType . "; charset=UTF-8");
    } else {
        header("Content-Type: " . $contentType);
    }
    
    echo $contentData;
    curl_close($ch);

} else {
    header("Content-Type: text/html; charset=UTF-8");
    echo "<h1>Content Proxy</h1><p>This proxy requires a 'file' GET parameter with a URL-encoded content URL.</p>";
}

個人用ツール
名前空間

変種
操作
案内
ツール
Translate