web-dev-qa-db-ja.com

PHP / Apacheを使用して静的ファイル(html、css、imgなど)へのアクセスを制限する

サーバー上のディレクトリ内に多数のhtml、css、js、imgなどのファイルがあるとします。通常、インターネットの土地にいるユーザーは、次のように完全なURLを入力するだけでこれらのファイルにアクセスできます。 http://example.com/static-files/sub/index.html

では、承認されたユーザーだけがそれらのファイルを読み込めるようにしたい場合はどうでしょうか。この例では、ユーザーが最初に次のようなURLからログインするとします: http://example.com/login.php

ログインしたユーザーがindex.htmlファイル(または「static-files」の下にあるファイルのいずれか)を表示することをどのように許可し、ファイルを他のすべてのユーザーに制限しますか?

これまでに2つの可能な解決策を考え出しました。

解決策1
「static-files」の下に次の.htaccessファイルを作成します。

Options +FollowSymLinks  
RewriteEngine on  
RewriteRule ^(.*)$ ../authorize.php?file=$1 [NC]

そしてauthorize.phpで...

if (isLoggedInUser()) readfile('static-files/'.$_REQUEST['file']);
else echo 'denied';

このauthorize.phpファイルは大幅に単純化されていますが、アイデアは理解できます。

解決策2
「static-files」の下に次の.htaccessファイルを作成します。

Order Deny,Allow
Deny from all
Allow from 000.000.000.000

次に、ログインページで、.htaccessファイルに、ログインする各ユーザーのIPを追加します。明らかに、これには、古いIPまたは使用されなくなったIPを削除するためのクリーンアップルーチンも必要です。


これらのソリューションのどれがより良く聞こえますか、そしてなぜですか?または、これらのどちらよりも優れた完全に異なるソリューションを考えることができますか?

39
Bart

PHPローダーを使用して認証を処理し、必要なファイルを返すことを検討します。たとえば、<img src='picture.jpg' />の代わりに<img src='load_image.php?image=picture.jpg' />のようなことを行います。

イメージローダーは、セッションの確認、資格情報の確認などを行い、要求されたファイルをブラウザーに返すかどうかを決定できます。これにより、すべての安全なファイルをWebアクセス可能なルートの外部に保存できるため、誰もそれらをWGETしたり、「誤って」参照したりすることはありません。

PHPで適切なヘッダーを返し、phpでreadfile()のようなことを行うことを忘れないでください。そうすれば、ファイルの内容がブラウザーに返されます。

私はいくつかの大規模で安全なWebサイトでこの設定を使用しましたが、それは魅力のように機能します。

編集:私が現在構築しているシステムは、このメソッドを使用してJavascript、画像、ビデオをロードしますが、CSSは安全性についてあまり心配していません。

35
Shane

X-Sendfile

Apache(およびその他のHTTPサーバー)用のモジュールがあり、これを使用して、PHPコードのヘッダーで指定したファイルをHTTPサーバーに提供することができます。したがって、phpスクリプトは次のようになります。

// 1) Check access rights code
// 2) If OK, tell Apache to serve the file
header("X-Sendfile: $filename");

2つの考えられる問題:

  1. ルールを書き換えるためのアクセス権が必要です(.htaccessが有効か、設定ファイルへの直接アクセス)
  2. インストールされているApacheにmod_xsendfileモジュールを追加する必要があります

これが別のスレッドでの良い答えです: https://stackoverflow.com/a/3731639/2088061

8
DenisS

私は同じ問題について多くのことを考えてきました。 PHPエンジンが実行されるすべての小さなリソースで実行されているエンジンにも不満があります。数か月前に同じように質問しました こちら 、ただし焦点が異なります。

しかし、私はちょうど恐らく面白いアイデア可能性があるが機能することを知りました。

  • _/sessions_というディレクトリをWebサーバーのどこかに保持します。

  • ユーザーがログインするたびに、_/sessions_にセッションIDを含む空のテキストファイルを作成します。例えば。 _123456_

  • PHPアプリで、次のような画像を提供します:_/sessions/123456/images/test.jpg_

  • Htaccessファイルに、2つのリダイレクトコマンドを記述します。

  • _/sessions/123456/images/test.jpg_を_/sessions/123456?filename=images/test.jpg_に変換するもの

  • //sessions/(.*)への呼び出しをキャッチし、_-f_フラグを使用して、指定されたファイルが存在するかどうかを確認する2番目のファイル。 _/sessions/123456_が存在しない場合は、ユーザーがログアウトしたか、セッションが期限切れになったことを意味します。その場合、Apacheは403を送信するか、エラーページにリダイレクトします-リソースは使用できなくなります。

このようにして、mod_rewriteに「ファイルが存在する」チェックを1つだけ行う疑似セッション認証があります。

その場でmod_rewriteステートメントを作成するのに十分なルーチンはありませんが、書くのは簡単です。 (私はうまくいけばあなたの方向@ガンボを探しています:)

注と警告:

  • 有効期限が切れたセッションファイルは、.htaccessでファイルのmtimeを確認することが可能でない限り(おそらく可能である)、cronジョブを使用してすばやく削除する必要があります。

  • 画像/リソースは利用可能すべてのクライアントへセッションが存在する限り、100%保護されません。クライアントIPを数式(=作成したファイル名)に追加して%{REMOTE_ADDR}の追加チェックを行うことで、この問題を回避できます。これは高度な.htaccessの習得ですが、それが実行可能であると確信しています。

  • リソースURLは静的ではなく、ログイン時に毎回取得する必要があるため、キャッシングはありません。

私はveryに関するフィードバック、見過ごされている可能性のある不足や不可能性、実装の成功に興味があります(現在、自分でテストをセットアップする時間はありません)。

5
Pekka

ユーザーの資格情報を検証し、それらを適切なリソースまたは「アクセス拒否」ページにリダイレクトする rewrite map を作成します。

Htaccessファイルの内容を維持することは悪夢のようです。また、指定された目的は、認証されていないユーザー認証されていないクライアントIPアドレスではないユーザーがこのコンテンツにアクセスできないようにすることです。アプローチが目的に合わない:

複数のユーザーが同じIPアドレスから来ているように見える

1つのユーザーセッションが複数のアドレスから送信されているように見える場合があります。

アクセスするユーザーとファイルの数が増えると、最初のソリューションがサーバーでかなり高価になるのではないかと心配しています。

コンテンツの漏出を防ぎ、HTTP認証を使用したくない場合は、すべてのファイルアクセスを追加のロジックレイヤーでラップすることが賢明な選択です。また、PHP for this isの使用が問題であることを知っていますか?テストしたことがありますか?スループットにどれだけのスループットがあるか、驚くと思います。特にopcodeキャッシュを使用している場合は、配信します。

ラッパーの「単純化」がMIMEタイプやキャッシングなどの問題に対処していると思います。

C.

2
symcbean

Apacheを使用している場合は、以下のように、.htaccessまたはhttpd.confファイルで構成できます。以下は、*。incファイルへのアクセスを禁止する例です。それは私には大いに役立ちます。

<Files ~ "\.inc$">
Order allow,deny
Deny from all
</Files>

http://www.ducea.com/2006/07/21/Apache-tips-tricks-deny-access-to-certain-file-types/ で詳細を参照してください。

0
Hieu Phan

すべての静的ファイルを保護し、それらをwebroot内からサーバーする必要があると仮定すると、HEADを除くすべてのHTTPメソッドを保護できます。承認されている場合は、headリクエストでヘッダーを通過させ、filecontentを本文として送信します。確かにこれは高価ですが、あなたは保護されており、同じ行動をします。

0
Andreas Dyballa

動的Webアプリケーションを作成してWebshere Application Serverにデプロイしました。静的ファイルを保護する方法を次に示します。

私は最初に追加しました

<login-config id="LoginConfig_1">
  <auth-method>FORM</auth-method>
    <realm-name>Form-Based Authentication</realm-name>
      <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/login_error.html</form-error-page>
       </form-login-config>
</login-config>

フォームベースの認証を使用するようにWebサーバーに指示するweb.xml内(ログインを使用するためのコードを以下に示します)。

ログインページへのコード:

<form id="form1" name="form1" method="post" action="j_security_check" style="padding: 0px 0px 0px 12px;">
        Username: 
          <label>
          <input name="j_username" type="text" class="font2" />
        </label>

        <br />
        <br />
        Password:
        <span class="font2" >
        <label>
      <input name="j_password" type="password" class="font2" />
      </label>
      </span> 
        <br />
        <br />
            <label>
        <input type="submit"  class="isc-login-button" name="Login" value="Login" />
        </label>
    </form></td>

フォームベースのログインを実行するには、LDAPまたはデータベースである特定のユーザーレジストリを使用するようにWebサーバーを構成する必要があります。

安全なリソースを宣言できます。ユーザーがそれらのリソースコンテナーにアクセスしようとするたびに、ユーザーが認証されているかどうかが自動的にチェックされます。安全なリソースを使用して役割を添付することもできます。これを行うには、web.xmlに次のコードを追加しました

<security-constraint>
        <display-name>Authenticated</display-name>
        <web-resource-collection>
            <web-resource-name>/*</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>PUT</http-method>
            <http-method>HEAD</http-method>
            <http-method>TRACE</http-method>
            <http-method>POST</http-method>
            <http-method>DELETE</http-method>
            <http-method>OPTIONS</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>Auth Roles</description>
            <role-name>role1</role-name>            
            <role-name>role2</role-name>            
        </auth-constraint>
    </security-constraint>

    <security-role>
        <role-name>role1</role-name>
    </security-role>
    <security-role>
        <role-name>role2</role-name>
    </security-role>

したがって、このコードでは、ユーザーがロールrole1およびrole2でログインするまで、静的ファイル(/ *以降)は表示されません。したがって、この方法でリソースを保護できます。

0
GG.

iframeHTTP_REFERERに基づいた提案があるかもしれませんが、それは完全な証拠ではなく、このアクセスで何を保護したいかによって異なります。

ただし、認証なしで完全な静的ページが表示されないようにする場合は、次のように実行できます。

1-PHPページを使用してユーザーを認証します

2-別のPHPページにリダイレクトします。URLにキーがあり、本文の静的コンテンツにリンクしているiframeがあります:

<iframe src="static/content.html" />

3-次に、htaccessで次のようにHTTP_REFERER内のキーを確認します。

RewriteEngine On
RewriteCond %{HTTP_REFERER} !AUTH_KEY
RewriteCond %{REQUEST_URI} ^/path/to/protected/page$
RewriteRule . - [F]

4-最後に、より動的にし、毎回同じKEYを使用しない場合は、Ignacio Vazquez-Abramsの回答で提案されているrewrite mapを使用するか、ユーザーIPをファイル名として使用してファイルを作成し、ファイルかどうかを確認しますREMOTE_ADDRを使用して存在し、しばらくしてからファイルを削除してください。

ただし、iframe + HTTP_REFERERの動作は、REMOTE_ADDRと同様に、ブラウザーセッションごとに異なる可能性があるため、制限があります...

0
RafaSashi