.Dev.Record

#6232031037c02

特定のIPの場合にBasic認証をかけずにサイトにアクセスさせる方法

2022.03.17

test

システム開発をしていると、ステージング環境やリリース前の本番環境にはBasic認証をかけておくことが多いと思います。

ですが、まれに特定のIPの場合にBasic認証なしでアクセスさせたい場合があります。

実務でのケース

筆者が遭遇したケースでは、開発中のシステムにはサイト内検索を導入することが決まっており、実現するためにはクローラーがサイト内を循環しなければなりませんでした。 ですがBasic認証がかかったままではクローラーがアクセスできません。なのでクローラー元のIPがアクセスした場合のみBasic認証をはずす必要がありました。

本記事では下記の場合の.htaccessの記述を備忘録的に解説しておきたいと思います。

想定するケース

  • 特定のIP1はBasic認証をかける
  • 特定のIP2はBasic認証をせずにアクセスさせる
  • 上記以外のIPはアクセス不可

Apacheのバージョンは2.4とします。

完成系

完成系は下記になります。

.htaccess

1<RequireAny>
2    # Basic認証の設定
3    <RequireAll>
4      AuthUserfile /パス/.htpasswd
5      AuthName "Please enter your ID and password"
6      AuthType Basic
7      require valid-user
8      <RequireAny>
9        Require ip <Basic認証をかけたいIP>
10      </RequireAny>
11    </RequireAll>
12
13    # Basic認証をせずにアクセスさせる設定
14    <RequireAll>
15      Require ip <Basic認証をせずにアクセスさせたいIP>
16    </RequireAll>
17</RequireAny>

解説

上記の.htaccessの中で押さえておきたいものは<RequireAny><RequireAll>の2つです。以降で解説します。

RequireAny、RequireAll

<RequireAny><RequireAll>はアクセス制御をコントロールする役割を果たします。

挙動としては<RequireAny>内に記載した条件の内一つ<RequireAll>すべての条件に一致していればアクセスを許可します。

使用例としてはRequireAny、RequireAllそれぞれ以下のような形です。

RequireAny使用例

1<RequireAny>
2    Require ip xxx.xxx.xxx.xxx
3    Require ip yyy.yyy.yyy.yyy
4</RequireAny>

この例ではRequireAnyを使用しているので、IPがxxx.xxx.xxx.xxxyyy.yyy.yyy.yyyのどちらかの場合にアクセスできます。

それ以外のIPは条件に一致しないのでアクセスできません。

RequireAll使用例

1<RequireAll>
2    Require ip xxx.xxx.xxx.xxx
3    Require host host-name-1
4</RequireAll>

この例ではRequireAllを使用しており、IPがxxx.xxx.xxx.xxxかつホスト名がhost-name-1の場合にアクセスできます。

RequireAnyではないので、IPがxxx.xxx.xxx.xxxで片方の条件は満たしていても、ホスト名がhost-name-2のようにもう片方の条件がみたされていなければアクセスできません

Memo

<RequireAny><RequireAll>はプログラミングでいうところのif文に似ていると思えば理解しやすいかもしれません。

<RequireAny>if(条件1 || 条件2)OR条件で、<RequierAll>if(条件1 && 条件2)AND条件をそれぞれ指定しているイメージです。

このようなアクセス制御を行うディレクティブは全部で3つあります。

アクセス制御ディレクティブ

  • RequireAll
    • すべての条件に一致していればアクセスを許可(AND条件)
  • RequireAny
    • いずれかの条件に一致していればアクセスを許可(OR条件)
  • RequireNone
    • すべての条件に一致しなければアクセスを許可(NOT条件)
    • RequireAllディレクティブ内でのみ使用可能

下記のように入れ子で使用することもできます。

入子の例

1<RequireAny>
2
3    # 条件1
4    <RequireAll>
5        # Basic認証の設定
6        AuthUserfile /パス/.htpasswd
7        AuthName "Please enter your ID and password"
8        AuthType Basic
9        require valid-user
10
11        # 条件1-1
12        <RequireAny>
13          Require ip xxx.xxx.xxx.xxx
14          Require ip yyy.yyy.yyy.yyy
15        </RequireAny>
16
17        # 条件1-2
18        <RequireAny>
19          Require host host-1
20          Require host host-2
21        </RequireAny>
22
23    </RequireAll>
24
25    # 条件2
26    <RequireAll>
27      Require ip yyy.yyy.yyy.yyy
28    </RequireAll>
29</RequireAny>

上記の例では、条件1条件2どちらかを満たせばアクセスが可能になります。

条件1の内部を見てみるとRequireAnyで一致条件を指定している以外にも、Basic認証の記述をしているのが分かるかと思います。

この場合条件1に一致した際はBasic認証が適用されることになります。

同じような理屈で条件2の方は一致条件しか指定していないため、条件2に一致した場合はBasic認証なしでアクセスが可能になります。

完成系(再掲)

ここまでで、再度完成系を眺めてみると何をしているのかなんとなくわかるのではないでしょうか?

.htaccess

1
2# RequireAnyなのでディレクティブ内のいずれかの条件に一致した場合アクセス可能
3<RequireAny>
4    # 条件1
5    # この条件に一致した場合はBasic認証をかける
6    <RequireAll>
7      # Basic認証の設定
8      AuthUserfile /パス/.htpasswd
9      AuthName "Please enter your ID and password"
10      AuthType Basic
11      require valid-user
12
13      # 条件1の一致条件
14      <RequireAny>
15        Require ip <Basic認証をかけたいIP>
16      </RequireAny>
17    </RequireAll>
18
19    # 条件2
20    # この条件に一致した場合はBasic認証をせずにアクセスさせる
21    <RequireAll>
22      Require ip <Basic認証をせずにアクセスさせたいIP>
23    </RequireAll>
24</RequireAny>

ここまでで解説したことを応用すれば、Basic認証以外にも様々な制御が可能になるかと思いますので試してみてください!

.Dev.Record