את הייתרונות (או החסרונות) של מנגנון ה-htaccess כבר סקרתי בעבר במאמר המשווה בין htaccess ל-php.ini
הפעם, נדבר יותר לעניין – מה אפשר לעשות באמצעות htaccess וכיצד?
אזהרה
שימו לב כי שינוי ה-htaccess גורם בפועל לשינוי בתשתית (תזכורת: htaccess נתון לנו את הכוח לשנות הגדרות ברמת השרת [שמשפיעות רק עלינו] במקום מנהלי השרת).
למה אזהרה? פשוט מכיון שאיש system הוא לרוב מנוסה יותר בשינויים כאלו, ו"הגולש הפשוט" – פחות מנוסה ומתבסס על מדריכי copy+paste.
חשוב לשמור בכל זמן על גיבוי לקובץ ה-Htaccess שלכם לפני ביצוע השינויים, במידה ועשיתם שינוי והאתר מחזיר לכם שגיאה 500 ("Internal server error") יש לבצע 2 דברים, ובמהירות (על מנת להחזיר את האתר לאוויר):
- לשחזר את הקובץ הישן (אם לא גיביתם, שווה אולי לבדוק את שירותי הגיבוי של חברת האחסון).
- להביט ב-Error log ולראות למה קיבלתם הודעת 500, ה-ERROR LOG זמין לכם (לרוב) באמצעות ממשק הניהול שלכם, במידה ואתם לא מכירים את המיקום, פשוט צלצול (או שלחו) מייל לחברת האחסון שלכם ובקשו את המידע הרלוונטי.
הודעת השגיאה אמורה להציג לכם במדוייק (ברמת השורה בתוך הקוד) למה ארעה השגיאה.
לרוב, השגיאה תתרחש בגלל שגיאת תחביר (syntax error) או שהשרת לא תומך ב-Feature שניסיתם לשנות.
תזכורת כללי לתצורת העבודה של קבצי Htaccess
- חילחול: קובץ htaccess בתיקיה אחת ישפיע על התיקיות תחתיו (אלה אם שמנו בתיקיה תחתיו הוראה סותרת).
- לא ניתן לגישה מבחוץ: שרת ה-APACHE מגיע עם "הגנה מובנית" שלא נותנת לגשת לקובץ הhtaccess מבחוץ (כלומר, אם תנסו לגלוש לכתובת https://www.hostingblog.co.il/.htaccess הגישה תדחה).
- השפעה מיידית: כל שינוי שאתם מבצעים בקובץ נכנס לפעולה עם שמירת הקובץ, אין צורך באתחול של משהו.
- תנאי עבודה: הקובץ יוכל לשנות רק את ההגדרות שמנהלי השרת אפשרו באופן ישיר (באמצעות AllowOverride בהגדרות ה-APACHE הכלליות).
מדריכי Copy+paste
טוב, אז אחרי שהמצפון שלי רגוע (או במילים אחרות, הטיפים שאני אציג בהמשך לא יכולים לגרום לכם נזק), נתחיל בהמלצות.
מניעת / אפשור גישה
דמיינו את המצב הבא, יש עמוד שאנחנו מעוניינים מסיבה כלשהי (עמוד בבניה, עמוד למורשים בלבד) למנוע (או לאפשר) את הגישה אליו. htaccess הוא פתרון טוב לשם ביצוע העניין, ניתן לבצע זאת בצורה פשוטה יחסית:
התניה הבאה תמנע מכלל האנשים (כולל אתם) לגשת לקובץ
deny from all
לעומת זאת, יכול לאפשר את הגישה לכתובות IP מסויימות
Order Allow,Deny
Deny from All
Allow from 192.168.1.2השורה הראשונה תגדיר את הסדר בו אנחנו מעבירים את הפקודות לשרת (קודם כל כבד את כל הוראות ה-Allow לאחר מכן את הוראות ה-Deny – ללא הקשר בו נכתבו ההראות בפועל).
כלומר, במקרה זה, אנחנו קודם כל נאפשר לכל מי שמגיע מהכתובת 192.168.1.2 להכנס לאתר
שימו לב שבמקרה הנ"ל, אנחנו נמנע את הגישה לכלל האלמנטים בתיקיה בה נמצא ה-Htaccess (וזאת מכיוון שההוראות שלו "מחלחלות" כלפי מטה בעץ התיקיות), ומה אם נרצה לא להשפיע על כל האלמנטים בתיקיה, אלה לדוגמא.. על קבצי CSS בתיקיה?
במקרה כזה, נשנה את החוק כך שיראה בצורה הבאה:
<FilesMatch "\.(css|style)$">
Order Allow,Deny
Deny from All
Allow from 192.168.1.2
</FilesMatch>במקרה הזה, אנחנו רואים שהחוקים נראים זהים, אבל הוספנו אותם בתוך פתיח-וסוגר בשם FilesMatch, והחלנו אותו על סיומת קבצים של css או style בלבד – כלומר, במקרה כזה, שאר הקבצים בתיקיה לא יושפעו מההתניה.
התניות
אם כבר התחלנו לדבר על התניות, בואו נעשה shift קצר ונדבר עליהן.
יש עוד מספר רב של התניות שניתן לבצע:
<IfModule mod_gzip.c>: התניה שתכנס לפועל רק במידה ומודול בשם mod_gzip מתוקן בשרת
<Files ~ "^\.ht">: התניה שתכנס לפועל רק אם שם הקובץ יתחיל באותיות ht
הפניית 301
הפניית 301 היא הפנייה שבה אנחנו אומרים למנוע החיפוש השונים שההפניה היא קרובה (בניגוד להפניית 302, בה מדובר בהפניה זמנית) – ההבדל בניהם הוא בעיקר באופן שמנועי החיפוש מאנדקסים את הנתונים – ההגיון אומר שהפניית 302 לא תאונדקס (הרי היא זמנית) ואילו הפניית 301 היא קבועה, ולכן יש לאנדקס אותה.
כיצד מבצעים? יש כמה "רמות" לביצוע:
הפניה של עמוד ספציפי לעמוד אחר
Redirect 301 /old/file.html http://yourdomain.com/new/file.html
הפניה של כל העמודים בתוך תיקיה מסויימת לתוך המקום המקביל בדומיין החדש
RedirectMatch 301 /blog(.*) http://yourdomain.com/$1
העברת כלל האתר מדומיין X לדומיין Y
RewriteEngine On
RewriteRule ^(.*)$ http://newdomain.com/ [R=301]
"אילוץ" האתר לעבוד עם WWW
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ http://example.com/$1 [L,R=301,NC]
"אילוץ" האתר לעבוד בפרוטוקול SSL
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]בדוגמא זו, ניתן לראות שאנחנו ראשית "בודקים" האם אנחנו לא נמצאים ב-HTTPS, במידה וכן, אנחנו נבצע Redirect לאותה הכתובת אליה ניגשנו – רק הפעם, בתוספת HTTPS.את אותה הבדיקה נבצע גם במידה וניגשנו ל-WWW וגם אם לא ניגשנו ל-WWW.
ביצוע Redirect של כל העמודים עם סיומת מסויימת לסיומת חדשה
RewriteEngine On
RewriteCond %{REQUEST_URI} .php$
RewriteRule ^(.*).php$ /$1.htm [R=301,L]
ביצוע Redirect של כתובת מסויימת לכתובת עם משתנים
לדוגמא: product.php?id=12 to product-12.html (או כל מספר מוצר אחר)
RewriteRule ^product-([0-9]+)\.html$ product.php?id=$1
הוספת Mime Type
MimeType הוא בעצם "הוראה" שהשרת שולח ומסביר לדפדפן כיצד יש להתמודד עם הקובץ.
זו בעצם הסיבה למה עמודי PDF נפתחים לנו אוטומטית בדפדפן ואפילו קבצי ZIP מבקשים אישור על מנת לרדת למחשב שלנו (ולא נפתחים בדפדפן כמו PDF).
לפעמים, השרת לא מכיל את כל ההוראות עבור כל סוגי הקבצים – אנחנו יוכלים להוסיף זאת באופן עצמאי:
AddType audio/mp4a-latm .m4a
כלומר, אנחנו נגיד לשרת – להגיד לדפדפן, שקבצים עם סיומות m4a יש לפתוח באמצעות תוכנה התומכת ב-audio/mp4a-latm
הוספת Server handler
אם הוספת mime-type בעצם "מסבירה" לדפדפן איך לפתוח את הקובץ, הוספת Handler "סביר" לשרת איך לפתוח את הקובץ.
AddHandler server-parsed .shtml
בדוגמא זו, אנחנו נסביר לשרת כיצד יש לפתוח דפי shtml
שימו לב שדוגמא זו נמצאת גם בשימוש רחב ע"י האקרים (לדוגמא, האקר מעלה קוד זדוני לשרת עם סיומת של jpg, מכיוון שהסיומת היא jpg, השרת לא ינסה "להריץ" את הקובץ – יחד עם זאת, אם נגיד לשרת באמצעות Htaccess שבסיומת jpg יש לטפל באמצעות ה-Php-handler, נוכל להגיד לשרת "לפתוח" קבצי תמונה כקובץ Php).
נתינת הוראות Cache לדפדפן
באמצעות htaccess, אנו יכולים לתת הוראה לדפדפן לבצע Cache לקבצים סטטים (html, css, js וכו') שלא צפויים להשתנות.
ה-Cache הוא לפי סוג קובץ ולזמן מוגבל (כמה שנגדיר), לדוגמא:
<filesmatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$"="">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2015 20:00:00 GMT"
Header unset Last-Modified
</filesmatch>בדוגמא זו, אנו נותנים הוראה לדפדפן לשמור CACHE מקומי עבור מגוון רחב של סיומות (ico,pdf,flv,jpg וכו').
עד מתי לשמור את ה-CACHE? עד ה-15 לאפריל 2015 בשעה 8 בערב.
את אותה הדוגמא ניתן ליישם בדרכים נוספות ומקוריות, לדוגמא:
<FilesMatch "\.(xml|txt|html|js|css)$">
ExpiresDefault A86400
Header append Cache-Control "private, must-revalidate"
</FilesMatch>בדוגמא זו נוכל לראות שאנחנו מבצעים CACHE עבור הסיומות xml, txt, html, js ו-css, ואומרים למחשב לזכור את התוצאות עד 86400 שניות (יממה) מרגע שינוי הקובץ (כלומר, מהרגע שאנחנו כבעלי האתר ערכנו את הקובץ – למעשה, אנחנו כבעלי האתר נותנים כאן הוראה לדפדפן של הגולש).
דוגמא אחרת יכולה להראות איך אנחנו לא מבצעים את הוראת ה-CACHE לפי סיומת, אלה לפי mime-type:
ExpiresByType application/x-javascript A86400
ExpiresByType application/javascript A86400
אגב, על מנת שכל הנושא הזה יפעל – השרת צריך לתמוך במודול בשם mod_expires.
במידה והוא לא תומך – אל דאגה, אתם כבר תדאו (תקבלו שגיאת 500 בנסיון להכניס את התוכן הנ"ל לקובץ ה-htaccess).
נתינת הוראת GZIP לדפדפן
כפי ש"אמרנו" לדפדפן לשמור CACHE עבור סיומת מסויימות, אנחנו גם יכולים לבקש ממנו לכווץ מידע המגיע מקבצים מסויימים (דבר שיחסוך בתעבורה > כלומר, יגרום לאתר לעלות מהר יותר – הדבר אומנם מעמיס מעט על השרת, אבל לא במידה שאמורה להדאיג אתכם).
היישום פשוט:
<filesMatch "\.(js|css|html|php)$">
SetOutputFilter DEFLATE
</filesMatch>בדוגמא זו אנו רואים כיצד ליישם GZIP עבור הסיומות js,css,html ועוד.
שימו לב, על מנת שהשרת יתמוך בפונקציה זו הוא צריך לתמוך ב-mod_deflate.
מניעת listing של התיקיה
מדובר על מקרה ספציפי בו אין לכם קובץ index כלשהו בתיקיה והגדרות האבטחה של חברת האחסון לא מסתירות את רשימת הקבצים בתיקיה.
הפתרון? פשוט:
Options -Indexes
שינוי הגדרות Php
שימו לב, לא כל הגדרת Php ניתנת לשינוי ולא בכל מקרה (שוב, אני ממליץ בחום לקרוא את המאמר הבא במידה וטרם קראתם).
איך מבצעים? לדוגמא:
php_value upload_max_filesize 20M
php_value post_max_size 20M
php_value max_execution_time 200
php_value max_input_time 200
חסימת דפדפנים / רובוטים
לפעמים אנו מעונינים למנוע מרובוטים מסויימים לגשת לאתר שלנו, זו דרך נוספת לחסום זאת:
SetEnvIfNoCase ^User-Agent$ .*(craftbot|download|extract|stripper|sucker|ninja|clshttp|webspider|leacher|collector|grabber|webpictures) HTTP_SAFE_BADBOT
SetEnvIfNoCase ^User-Agent$ .*(libwww-perl|aesop_com_spiderman) HTTP_SAFE_BADBOT
Deny from env=HTTP_SAFE_BADBOTכאשר השורה המכילה את המידע "craftbot|download" וכו' מכילה בעצם אילו מילים נאסור שיופיעו ב-UserAgent של הדפדפן / רובוט.
שליחת Headers למשתמש
לעיתים (בעיקר מול עבודה עם CDN), נתבקש לשלוח למשתמשים HEADER מסויים (למשל, HEADER שיגיד ל-CDN שבמידה ויש אותו למשתמש, לא לבצע CACHE לעמוד בו הוא נשתל) – גם את זה נוכל לעשות באמצעות HTACCESS, לדוגמא:
Header set P3P "policyref=\"http://www.askapache.com/w3c/p3p.xml\""
Header set X-Pingback "http://www.askapache.com/xmlrpc.php"
Header set Content-Language "en-US"
Header set Vary "Accept-Encoding"
שינוי קובץ ה-Index
כברירת מחדל, אנו רגילים כי קובץ ה-index (או יותר נכן, הקובץ הראשון שניגשים אליו בגלישה) הוא Index.html או Index.php
לדוגמא: כאשר אתה גולשים לאתר spd.co.il , בפועל, הכתובת הנטענת היא Index.php – פשוט מכיוון ש-index.php מוגדר כ-Index עבור אתר זה.
זוהי הגדרה הקיימת כברירת מחדל, אבל ניתן לשנותה – אם לדוגמא נבחר שה-Index שלנו הוא קובץ בשם Duboni-Ipatlit.html, נציב את ההוראה הבאה בקובץ ה-Htaccess שלנו:
DirectoryIndex Duboni-Ipatlit.html index.html index.php index.htm
בהוראה זו אנחנו אומרים לשרת לחפש קודם כל את הקובץ Duboni-Ipatlit.html, במידה והוא לא מוצא אותו, להמשיך ולחפש את Index.html וכך הלאה.
דפי שגיאה מותאמים אישית
בעבר (לפני עולם ה-CMS המוכנות דוגמאות WordPress ו-ג'ומלה) ה-Feature הזה היה יותר "להיט".
היום, הוא קצת איבד מהמקום שלו כי כל אותם CMS מציעות לנו לבצע את אותו הדבר בדיוק, ללא עבודה כלשהי מהצד שלנו (או לפחות, ללא הצורך לערוך קבצי htaccess).
הרעיון הוא פשוט, במקום שבמידה וניגשנו לעמוד שאינו קיים נקבל את הודעות ברירת המחדל של השרת – נציג עמוד משל עצמנו.
איך מיישמים?
ErrorDocument 401 /err/401.php
ErrorDocument 403 /err/403.php
ErrorDocument 404 /err/404.php
ErrorDocument 500 /err/500.php
שימו לב שהתחביר מורכב ממספר השגיאה ולאחר מכן הקובץ אותו נרצה להציג.
- ריבוי אתרים בחשבון = סיכון אבטחה - יולי 16, 2017
- Let's encrypt – תעודות SSL, ובחינם! - ינואר 17, 2017
- PHPMailer Exploit - דצמבר 28, 2016
השאר תגובה