7

私が働いている会社から、自社の Web サイトの 1 つを別の Web サイトのサブドメインにするように依頼されました。次に、「ログイン/ログアウト」セッション制御をプライマリ ドメインからサブドメインに拡張するように依頼されました。

これを行うと、制御/管理の問題があることがわかります。膨大な数の個々のページと、広範なディレクトリ構造のため、各ページに PHP スニペットを追加して、ログイン状態に基づいてリダイレクトするのは非常に複雑です。

これが私の解決策です..問題や、私に役立つ何か他のことを教えてください.

  1. Mod_rewrite を使用して、サブドメインのすべてのリクエストを特定のページ ( handler.php?requested_url= ) にリダイレクトします。
  2. 彼らのウェブサイトに「サイトの許可/禁止ルール」セクションを作成する予定です。このセクションには、次のようなルールを持つ 1 つのテキスト ボックスが含まれます。

     +/weather/            ---> will allow anyone access to any url that contains "/weather/" somewhere within it, irregardless of logged-in status.
    
     -/weather/premium/    ---> will only allow access to a url that contains /weather/premium to logged-in users. 
    

    これは、ファイルrules.phpに格納されている配列に出力され、次のようになります。

    $ruleList = array(); 
    $ruleList[] = '+/weather/'; 
    $ruleList[] = '-/weather/premium/';
    
  3. handler.phpでは、ユーザーがログインしている場合は、それらをrequested.urlに転送します。ユーザーがログインしていない場合は、すべてのページがログインしていないユーザーに制限されていると仮定することから始めます。handler.phpはrequested_urlを解析し、rules.phpに対してチェックして、明示的なアクセス許可が設定されているかどうかを確認します。次に、ルールが非ログイン アクセスを許可する場合は、ユーザーをrequested_urlに転送します。それ以外の場合は、ログイン ページに送信します。

すぐにわかる問題の 1 つは、Mod_rewriteルールがすべてのリクエストをhandler.phpに送信することを考えると、無限ループを回避するにはどうすればよいかということです。

以外の方法でリダイレクトを行う必要がありheader("Location: ")ますか?

編集:ここに私の闘争の更新があります:

最上位ドメイン (example.com)の.htaccessファイル内に次を追加しました。

    #Prevent catching requests for the sub1 subdomain
    RewriteCond %{REQUEST_URI} ^sub1\.example\.com
    RewriteRule .* – [L]

次に、sub1.example.com サブドメインの .htaccess 内に、追加しました。

    IndexIgnore *

    RewriteEngine On
    RewriteBase /path/to/base

    #Avoid infinite loop on outgoing requests
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{REQUEST_URI} !^$
    RewriteCond %{HTTP_REFERER} !^/?handler.php?$
    RewriteCond %{REQUEST_URI} !^/?handler.php?$



        #Check for cookie. Redirect to handler if not found.  (not yet implemented)                               
        #RewriteCond %{HTTP_COOKIE} !session_id
    RewriteRule (.*)$ handler.php?requested_url=$1 [NC,L,QSA]

これがhandler.phpです

    <?php

        $url = $_REQUEST['requested_url'];

        //Check list of permissions. For now just assume permitted.
        $permitted = true;
        if ($url == "") $url = "http://sub1.example.com";   
        if ($permitted)
            header("Location: ".$url);
        header("Location: http://sub1.example.com");        

    ?>

私はそれを味わうことができるほど近いです。残念ながら、当分の間、ほぼすべての場所で「リダイレクト ループ」が発生しています。誰かが私に正しい方向への微調整を与えることができれば、私はそれを感謝します!

4

4 に答える 4

3

単なるアイデアですが、おそらく mod_rewrite に苦労する必要はありません。とにかく PHP からすべてを処理したい場合は、VHOST にプリペンド ファイルを追加してみませんか?

php_value auto_prepend_file handler.php

PHPスクリプトの前に含まれ、必要に応じてリダイレクトできます。

于 2012-09-30T21:49:01.323 に答える
2

apache authを使用したくない理由はありますか?それほど複雑ではないと思います。 http://httpd.apache.org/docs/2.2/howto/auth.html

仮想ホスト内のアクセスルールをディレクトリごとに指定できます。ユーザー情報はフラットファイルまたはデータベースに含めることができます。

于 2012-09-22T04:03:39.157 に答える
2

あなたのアイデアにはループがあると思います。したがって、アプリケーションにループがあります。このような:

  1. ユーザー エージェントは、サブドメイン内のレガシー リソースを要求します。

  2. UA には有効な資格情報が必要であり、レガシー リソースは資格情報を検証できないため、UA はハンドラーにリダイレクトされます。

  3. ハンドラーは資格情報を検証し、UA をレガシー リソースにリダイレクトします。

  4. 2へ。

問題は、要求されたリソースが手順 1 と 3 で UA の要求を区別できないことです。これは、区別が UA の資格情報によって定義され、レガシー リソースでは評価されないためです。

この矛盾は、別の観点からも明らかです。ループを解決し、UA がレガシー リソース ( http://sub1.example.com/foo.phpなど) にリダイレクトされると想像してみてください。サーバーがリソースを返すには、資格情報が評価されていない (評価されていないため) ことを意味する必要があり、したがって、リソースは実質的に公開されています。

これを回避するには、ステップ 2 または 3 のルールを変更してデッドロックを打破する必要があります。

  • ステップ 2 を変更するには、資格情報の評価をレガシー リソースの応答に追加します。示唆している前の回答auto_prepend_file()はその方向に向かっていますが、PHP のレガシー ファイル (画像、HTML など) のみが対象です。

  • ステップ 3 を変更するには、UA がリソースを直接要求せずにレガシー リソースを配信する方法を見つけます。1 つの可能性は、ハンドラーがファイル システムからリソースを取得し、readfile()HTTP ヘッダー管理を使用してネットワーク上に配置することです。

おそらく、これらの組み合わせがうまくいくでしょう:auto_prepend_file()認証処理をレガシー PHP に適用し、readfile()PHP 以外のコンテンツに適用します。

于 2012-10-01T21:34:19.633 に答える
1

簡単な検証機能が必要です。ユーザーは、リソースへのアクセスを許可されているかどうかのいずれかです。したがって、まずコンテキストをセットアップします。

$rules          = rules_load();
$uri            = $_SERVER['QUERY_STRING'];
$userIsLoggedIn = user_is_logged_in();

その隣には、デフォルトで返されfalse、コンテキストをパラメーターとして受け取る前述の検証関数があります。

$validation = function (array $rules, $uri, $userIsLoggedIn) {
    $permitted = false;    
    return $permitted;
};

ロジックは簡単です。

if ($validation($rules, $uri, $userIsLoggedIn)) {
    # can pass
    echo "can pass";
} else {
    # login first
    echo "login first";
}

当然のことながら、すでに「最初にログイン」しています。罰金。その関数のパラメータをすぐに変更します。$rules方法を見て、$uriお互いに立ち向かいましょう。

各ルールは URI に一致する可能性があり、少なくともパスは可能です。ルールを分割しましょう:

 <sign><path>

 sign    := [+-]
 path    := <segment>*/
 segment := /[a-z]+

ルールが に一致するか、または一致しません$uri。一致する場合、符号はこれが何を意味するかを決定します。

つまり、実際には記号$uriで指定された 2 つのグループがあり、一致するかどうかが言えます。これも単純な関数です。最初に規則の配列が符号でフィルタリングされ、次にパスでフィルタリングされます。

URI と一致する配列の形式ですべてのルールのサブセットを返す 3 つの入力パラメーターを持つ関数を考えてみましょう。

function ($sign) use ($rules, $uri) {
    return array_reduce($rules, function ($a, $v) use ($rules, $sign, $uri) {
        $v[0] === $sign && false !== strpos($uri, substr($v, 1)) && $a[] = $v;
        return $a;
    }, array());
};

これは多かれ少なかれ への呼び出しarray_reduceです。したがって、これが呼び出された変数に関連付けられ、関数のパラメーターとして$match置き換えることができる$rulesと仮定しましょう。$uri$validation

$validation = function ($match, $userIsLoggedIn) {

したがって、残りの部分は、検証条件を作成するだけです。

    $permitted = $userIsLoggedIn;

デフォルトでは、ユーザーがログインしている場合、権限が付与されます。ユーザーがログインしていない場合にのみ、- グループが一致せず、+ グループが一致する場合に許可を付与できます。- グループは最初に来て、安全上の理由から + ルールをオーバーライドする必要があります。

    $permitted = $userIsLoggedIn ?: !$match('-') && $match('+');

残りはそのステータスを返すことです:

    return $permitted;
};

この関数はかなり自明なので、発行することができます。コードの全文:

$rules          = rules_load();
$uri            = $_SERVER['QUERY_STRING'];
$userIsLoggedIn = user_is_logged_in();

$match = rules_match($rules, $uri);

$permitted = $userIsLoggedIn ?: !$match('-') && $match('+');

if ($permitted) {
    # can pass
    echo "can pass";
} else {
    # login first
    echo "login first";
}

/**
 */
function rules_match(array $rules, $uri) {
    return function ($sign) use ($rules, $uri) {
        return array_reduce($rules, function ($a, $v) use ($rules, $sign, $uri) {
            $v[0] === $sign && false !== strpos($uri, substr($v, 1)) && $a[] = $v;
            return $a;
        }, array());
    };
}
于 2012-10-01T20:55:15.577 に答える