この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: .htaccess
SEOタイトル: Apache .htaccess 完全ガイド — リライト・認証・セキュリティ

この記事の要点
  • .htaccess は Apache のディレクトリ単位の設定ファイル。AllowOverride All が必要
  • 主用途: URL リライト / リダイレクト / Basic 認証 / IP 制限 / ディレクトリ一覧 OFF / ファイルアクセス禁止
  • RewriteEngine On + RewriteRule で URL 書き換え、HTTPS 強制、www 統一など
  • Basic 認証: htpasswd でパスワードファイル作成 → AuthType Basic / AuthUserFile
  • Nginx には .htaccess の概念は無い。同等は server / location ブロックで設定

.htaccess の基本

Apache HTTP Server でディレクトリごとに設定を上書きできる仕組みです。配置したディレクトリと配下に効果が及びます。サーバ全体の設定 (httpd.conf) を書き換えなくて済むのが利点。

有効化(AllowOverride)

# /etc/apache2/apache2.conf または /etc/httpd/conf/httpd.conf

    AllowOverride All          # ★ これが None だと .htaccess 無視
    Require all granted


# 設定後リロード
# sudo systemctl reload apache2
# sudo systemctl reload httpd

URL リライト (RewriteEngine)

# /var/www/html/.htaccess

RewriteEngine On

# 1. すべての URL を index.php に転送(フレームワーク前提:Laravel/CodeIgniter 等)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]

# 2. /old → /new (恒久リダイレクト)
RewriteRule ^old/(.*)$ /new/$1 [R=301,L]

# 3. www あり → www なし統一
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

# 4. HTTP → HTTPS 強制
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# 5. クエリ文字列で振り分け
RewriteCond %{QUERY_STRING} ^id=(\d+)$
RewriteRule ^show\.php$ /post/%1? [R=301,L]

リダイレクト (mod_alias)

# 301 恒久リダイレクト
Redirect 301 /old-page /new-page
Redirect 301 /docs https://docs.example.com

# 302 一時リダイレクト
Redirect 302 /campaign /landing

# ディレクトリ全体
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1

Basic 認証

# .htaccess
AuthType Basic
AuthName "Restricted Area"           # ダイアログに表示される名称
AuthUserFile /etc/apache2/.htpasswd  # ★ Web 公開外に置く
Require valid-user

# 特定ユーザだけ
Require user alice bob

# グループで管理
AuthGroupFile /etc/apache2/.htgroup
Require group admins

パスワードファイル作成:

# 新規作成(-c)
sudo htpasswd -c /etc/apache2/.htpasswd alice
# New password: ...
# Re-type new password: ...

# ユーザ追加(-c 無し)
sudo htpasswd /etc/apache2/.htpasswd bob

# 削除
sudo htpasswd -D /etc/apache2/.htpasswd bob

# 中身確認
cat /etc/apache2/.htpasswd
# alice:$apr1$xyz...

IP アドレス制限

# Apache 2.4+ 構文
# 特定 IP のみ許可
Require ip 192.168.1.0/24
Require ip 203.0.113.5

# 特定 IP のみ拒否(その他許可)

    Require all granted
    Require not ip 203.0.113.99
    Require not ip 10.0.0.0/8


# 認証 + IP のいずれかで OK

    Require ip 192.168.1.0/24
    Require valid-user


# Apache 2.2 以前(古い記法、混在環境注意)
Order Deny,Allow
Deny from all
Allow from 192.168.1

ディレクトリ一覧の無効化

# index.html が無いディレクトリで一覧表示されるのを防ぐ
Options -Indexes

# シンボリックリンクも禁止したい
Options -Indexes -FollowSymLinks

# CGI 実行禁止
Options -ExecCGI

# .htaccess を無効化(サーバ管理者用)
AllowOverride None

特定ファイル / 拡張子の保護

# .env / .git / .htaccess 自体を Web からアクセス不可に

    Require all denied



    Require all denied



    Require all denied


# 拡張子で

    Require all denied


# ディレクトリ単位

    Require all denied

キャッシュ / 圧縮

# 静的ファイルのキャッシュヘッダ

    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType text/css "access plus 1 week"
    ExpiresByType application/javascript "access plus 1 week"
    ExpiresByType text/html "access plus 5 minutes"


# gzip 圧縮

    AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json text/xml


# Brotli (mod_brotli 必要)

    AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript

セキュリティヘッダ


    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "geolocation=(), microphone=()"
    Header always unset X-Powered-By

    # CSP(厳密化したい場合)
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'"

カスタムエラーページ

ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html
ErrorDocument 503 /maintenance.html

Laravel 用 .htaccess 標準

# Laravel public/.htaccess(公式デフォルト)


    
        Options -MultiViews -Indexes
    

    RewriteEngine On

    # Authorization ヘッダの引き継ぎ
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # /index.php へリダイレクトする末尾スラッシュ
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # 存在しないファイル / ディレクトリは index.php へ
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

Nginx での同等設定

Nginx には .htaccess の概念がありません。すべて server / location ブロックで書きます:

server {
    listen 80;
    server_name example.com;

    # HTTPS 強制
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    root /var/www/html/public;
    index index.php;

    # 全リクエストを index.php へ(Laravel)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # ディレクトリ一覧 OFF
    autoindex off;

    # 隠しファイル拒否
    location ~ /\. {
        deny all;
    }

    # Basic 認証
    location /admin {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    # PHP
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

デバッグ: 反映されているか確認

# 構文チェック
sudo apachectl configtest

# モジュール確認
apachectl -M | grep rewrite      # rewrite_module (shared) と出れば OK
apachectl -M | grep headers
apachectl -M | grep auth_basic

# 有効化
sudo a2enmod rewrite headers
sudo systemctl restart apache2

# .htaccess が読まれているか
echo "Deny from all" >> .htaccess  # 一時的に
# → 全リクエストが 403 になれば反映されている

FAQ

Q: .htaccess の変更を即時反映するには?
A: 不要。配置・更新と同時に Apache が読み込みます。サーバ再起動は不要です。

Q: .htaccess を使うと遅い?
A: ディレクトリ階層をたどるたびに読み込むので性能を気にする本番では httpd.conf に書くのが定石です。

Q: 反映されない
A: ① AllowOverride All 確認 ② a2enmod rewrite ③ Apache 再起動 ④ .htaccess の文法エラー(error.log 参照)。