
내 스택:
- 램프
- 아파치/2.4.41
배경 정보:
나는 최근에 고객을 위한 새로운 웹사이트를 개설했습니다. 재설계 과정에서 우리는 다음과 같이 결정했습니다.
- 사이트 전체 HTTPS로 전환
- URL에서 .php 확장자를 제거하세요.
- CMS로 전환
이전 URL의 예:
http://www.example.com/courses/acme-course.php
새 URL의 예:
https://www.example.com/courses/acme-course
내 문제:
사용자가 이전 URL 중 하나로 이동할 때 불필요한 추가 301 리디렉션이 발생합니다.
추가 301 리디렉션이 생성되고 단일 301 리디렉션을 사용하여 사용자를 올바른 대상 URL로 직접 보내지 않는 이유를 이해할 수 없습니다.
흥미로운 관찰:
HTTP 대신 HTTPS로 OLD URL을 사용하면 불필요한 추가 301 Redirect가 발생하지 않습니다.
예:
https://www.example.com/courses/acme-course.php
_
위 URL을 사용하면 다음의 올바른 대상 URL로 단일 301 리디렉션이 올바르게 수행됩니다.https://www.example.com/courses/acme-course
다음은 301 리디렉션 체인의 예입니다.
원래 요청 URL:
http://www.example.com/courses/acme-course.php
첫 번째 301 리디렉션(불필요):
에서:
http://www.example.com/courses/acme-course.php
에게:
https://www.example.com/index.php?url=courses/acme-course.php
두 번째 301 리디렉션(올바른 최종 대상 URL):
에서:
https://www.example.com/index.php?url=courses/acme-course.php
에게:
https://www.example.com/courses/acme-course
내 .htaccess 코드:
# (1) General Settings
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
</IfModule>
# (2) Force WWW
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
# (3) Force HTTPS
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
# (4) URL Routing for CMS
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
## Check if file/directory exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
## Route all other URLs to index.php/URL
RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>
답변1
두 가지 주요 문제가 있습니다....
- 파일에서 지시문의 순서가 잘못되었습니다
.htaccess
. HTTP에서 HTTPS로의 리디렉션과www
표준 리디렉션이 필요합니다.~ 전에URL을 CMS로 라우팅하는 전면 컨트롤러입니다. 따라서/index.php?url=courses/acme-course.php
내부 CMS URL 구조를 노출시키는 잘못된 외부 리디렉션입니다 .
제거가 실제로 귀하의 지시
.php
에 따라 수행되지 않습니까 ?!.htaccess
나는 이것이 당신의 애플리케이션/CMS 로직에 의해 수행되어야 한다고 생각합니까? 결과적으로 이는언제나두 번째 리디렉션이 발생합니다(.htaccess
동일한 URL 경로에서 HTTPS로 리디렉션되기 때문). 확장자를.htaccess
제거하려면 파일 상단에서 다음과 같은 작업을 수행해야 합니다.php
.RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
업데이트:규칙/조건을 다시 정렬하면 옵션 +FollowSymlink 배치가 동일하게 유지됩니까?
별로 중요하지 않습니다어디지시문 Options
이 발생합니다. 그러나 (가독성의 관점에서) 상단 근처에 두는 것이 논리적입니다. (Apache 지시문은 각 모듈이 독립적으로 작동하므로 반드시 구성 파일에 나타나는 순서대로 실행될 필요는 없습니다.)
파일 을 직접 코딩한다고 가정하면 .htaccess
정리할 수 있습니다.
(다중) 래퍼가 필요하지 않습니다
<IfModule mod_rewrite.c>
. mod_rewrite는 선택사항인가요? 귀하의 사이트가 mod_rewrite가 활성화되지 않은 여러 서버로 포팅되었습니까?여러 지시어가 필요하지 않습니다
RewriteEngine
. 그만큼마지막실제로는승리전체 파일을 제어합니다.다중
<IfModule>
블록은RewriteEngine
코드에 의해 자동으로 편집되거나 다중 서버에서 편집되지 않은 상태로 작동하도록 설계된 시스템의 전형적인 형태입니다.
따라서 .htaccess
파일은 다음 순서로 다시 작성되어야 합니다.
Options +FollowSymlinks
# Enable the rewrite engine...
RewriteEngine On
# ----------------------------------------------------------------------
# | Forcing `https://` |
# ----------------------------------------------------------------------
# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]
# ----------------------------------------------------------------------
# | Forcing `www` |
# ----------------------------------------------------------------------
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# ----------------------------------------------------------------------
# | URL Routing for CMS |
# ----------------------------------------------------------------------
# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]
추가 참고 사항:
환경
PROTO
변수에는 요청되는 모든 프로토콜이 포함됩니다. 리디렉션 순서에 따라 이제 항상 HTTPS가 됩니다. 이 변수를 사용하는 이유는 CMS가 HTTP에 액세스하는 경우 HTTP로 리디렉션하거나 HTTPS에 액세스하는 경우 HTTPS로 리디렉션할 수 있기 때문입니다. HTTPS를 강제하는 경우에는 실제로 적용되지 않습니다. (이 환경 변수는 애플리케이션에서 계속 사용될 수 있습니다.)NC
부정된 조건에 플래그를 사용하는 경우는 거의 없습니다 . 그러므로 조건에서 그것을 제거한 이유는 무엇입니까!^www\.
? 호스트가www.
모두 소문자 로 시작하지 않을 때 리디렉션을 원합니다 . 플래그를 사용하면NC
리디렉션에 실패합니다WwW.
. 어쨌든 이는 매우 드뭅니다.www 표준 리디렉션에서 불필요한 HTTPS 확인을 제거했습니다.
PT
에서는 마지막 플래그가 필요RewriteRule
하지 않습니다.htaccess
. 이것이.htaccess
기본 동작(통과)입니다.잘못된 301 리디렉션이 브라우저에 캐시되었을 가능성이 높으므로 테스트하기 전에 브라우저 캐시를 지워야 합니다. 이러한 이유로 302(임시) 리디렉션으로 테스트하는 것이 좋습니다.