web-dev-qa-db-fra.com

Le code htaccess pour empêcher la création de liens hotlink ne fonctionne pas

J'ai beaucoup cherché ce sujet et trouvé ce morceau de code (ou de légères variations) dans de nombreux endroits, y compris des réponses sur ce site. C'est le code:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)mydomain.com/.*$ [NC]
RewriteRule \.(gif|jpg)$ - [F]
</IfModule>

Je ne suis pas un webmaster mais je peux comprendre ce que fait le code. Bien sûr, dans mon code, j'ai remplacé mydomain.com par mon domaine réel.

Le problème est que lorsque je mets ce code dans mon dossier racine, il détruit l’ensemble du site Web avec une erreur de 500. Si je le mets dans le sous-répertoire que je souhaite protéger, tous les fichiers du sous-répertoire ne sont plus accessibles à personne et sur le site Web, un espace réservé pour une image défectueuse est affiché. Qu'est ce qui ne va pas avec ça?

La raison pour laquelle j'ai besoin de ce code est que seuls les abonnés doivent pouvoir accéder aux fichiers. Je ne veux pas qu'ils partagent le lien et les rendent accessibles à quiconque. C'est un code de test, les vrais fichiers à protéger ont une extension différente de celle de gif ou jpg mais le principe est le même.

1
Ikagil

Si vos abonnés doivent se connecter à votre site Web, vous pouvez utiliser un script PHP dans votre dossier d'images pour vérifier qu'ils sont bien connectés avant de diffuser une image de la même manière que vous le feriez avant de leur envoyer un message. page Web réservée aux abonnés.

Votre fichier . Htaccess peut avoir:

# Protect subscriber-only assets from hot-linking (*.gif)
RewriteCond %{REQUEST_URI} (.*)\.gif
RewriteRule ^(.*\.)(gif)$ protected-asset.php?f=$1$2 [L]

# Protect subscriber-only assets from hot-linking (*.jpg)
RewriteCond %{REQUEST_URI} (.*)\.jpg
RewriteRule ^(.*\.)(jpg)$ protected-asset.php?f=$1$2 [L]

Et puis votre fichier protected-asset.php pourrait avoir:

<?php
$sWebrootPath = '/var/www/www.mydomain.com/';
$sAsset = isset( $_GET['f'] ) ? $sWebrootPath . $_GET['f'] : '';
$aHeaders = array();

/* HTTP 404 if asset does not exist */
if( !file_exists( $sAsset )) {
  header( 'HTTP/1.0 404 Not Found' );
  exit;
}

/* Check if request comes from authenticated subscriber */
require_once( 'classes/session.php' );
if( Session::UserId() == 0 ) {
  header( 'HTTP/1.0 401 Unauthorized' );
  exit;
}

/* Declare MIME-Type */
$sFileExt = strtolower( substr( $sAsset, 1+stripos( $sAsset, '.' )));
switch( $sFileExt ) {
  case 'gif': $sMimeType = 'image/gif'; break;
  case 'jpg': $sMimeType = 'image/jpg'; break;
  default: $sMimeType = 'text/plain'; break;
}
$aHeaders[] = 'Content-Type: ' . $sMimeType . '; charset: UTF-8';

/* Cache for 1 hour (you could extend this as required) */
$iCacheSecs = 60 * 60;
$dtNow = time();
$dtExpires = strtotime( sprintf( '+%s seconds', $iCacheSecs ));
$aHeaders[] = 'Expires: ' . date( 'r', $dtExpires );
$aHeaders[] = 'Last-Modified: ' . date( 'r', $dtNow );
$aHeaders[] = 'Cache-Control: public, must-revalidate, ' .
  sprintf( 'max-age=%s', $iCacheSecs );

/* Generate unique ETag */
$sData = @file_get_contents( $sAsset );
$sETag = md5( $sData );
$aHeaders[] = sprintf( 'ETag: %s', $sETag );

/* HTTP 304 if asset has matching ETag to browser cached copy */
$sSuppliedETag = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? 
  $_SERVER['HTTP_IF_NONE_MATCH'] : '';
if( $sSuppliedETag == $sETag ) {
  header( 'HTTP/1.1 304 Not Modified' );
  header( 'Content-Length: 0' );
  exit;
}

/* GZip Compression */
if( !ob_start( 'ob_gzhandler' )) ob_start();

/* Respond with Asset headers and data */
foreach( $aHeaders as $sHeader ) header( $sHeader );
echo( $sData );

Les deux extraits du code ci-dessus qui ne fonctionneront pas immédiatement et qui devront être remplacés par votre propre code sont les suivants: require_once( 'classes/session.php' ); et Session::UserId(). Le principe ici est que require_once charge tous les fichiers prérequis nécessaires pour identifier si une personne est connectée ou non, et ma fonction UserId () renvoyait 0 pour indiquer qu'aucun utilisateur authentifié n'était affecté à la session en cours. Vous devrez probablement utiliser un cookie pour gérer vos sessions, etc., mais il semblerait que la partie de connexion de votre abonné que votre site Web a déjà été configurée et qu'elle fonctionne. Il vous suffit donc de copier du code pour remplacer ces deux parties.

En principe, je suis plutôt partisan des meilleures pratiques, mais en règle générale, je ne place pas les instructions <IfModule> dans des fichiers . Htaccess car ils peuvent généralement causer plus de problèmes qu'ils n'en résoudent d'après mon expérience - cela peut Vaut la peine d'essayer votre code existant sans ceux-ci avant d'essayer ma solution!

2
richhallstoke