Возможно, вы могли бы использовать базовый подход CSRF и загружать шрифт только один раз за запрос, создавая ключи сеанса, срок действия которых истекает после одного использования, и проверяя реферер (который может сломаться, если пользователь очищает его при последующих запросах).
Но для того, чтобы что-то сделать ;p Я собрал пример того, что я имею в виду, это не 100%, но это предотвратит попытки широкой публики получить прямой доступ к шрифту. скачать исходный пример
Используя этот метод, чтобы получить шрифт, вам необходимо:
- Сделать запрос к странице, не загружая шрифт css. (фгк, завиток, т. д.)
- Разобрать исходники страниц и получить ключи из CSS.
Затем сделайте собственный запрос к загрузчику шрифтов, установив реферер и используя пары ключ-значение.
- Perhaps it will pass there expectations of protection.
CSS, что вы можете сделать, это вместо указания пути к шрифту использовать PHP для загрузки шрифта, таким образом вы можете добавить некоторые одноразовые номера в запрос.
@font-face {
font-family: 'TheFontName';
src: local('TheFontName'), url('<?php echo SITE_URL.'/fonts.php?font=TheFontName.woff&'.$_SESSION['font_csrf_key'].'='.$_SESSION['font_csrf_token']?>') format('woff');
font-weight: normal;
font-style: normal;
}
Пример (index.php)
<?php
/**
* @name ProtectFont
* @link https://www.dropbox.com/s/xsbpw4g3xn4fzai/ProtectFont.zip
*/
session_start();
//Define paths
define('BASE_FOLDER', dirname($_SERVER['SCRIPT_NAME']));
define('SITE_ROOT', pathinfo($_SERVER['SCRIPT_FILENAME'], PATHINFO_DIRNAME));
define('SITE_URL', rtrim( 'http://'.$_SERVER['HTTP_HOST'].BASE_FOLDER, '/'));
//Site host will be checked against as the referrer host
define('SITE_HOST', parse_url(SITE_URL, PHP_URL_HOST));
/* Now for the font protection, we create 2 CSRF keys,
one for the $_GET key and the other as the value.
*/
$_SESSION['font_csrf_key'] = sha1(uniqid());
$_SESSION['font_csrf_token'] = sha1(uniqid());
?>
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
@font-face {
font-family: 'TheFontName';
src: local('TheFontName'), url('<?php echo SITE_URL.'/fonts.php?font=TheFontName.woff&'.$_SESSION['font_csrf_key'].'='.$_SESSION['font_csrf_token']?>') format('woff');
font-weight: normal;
font-style: normal;
}
body {
font-size: 110%;
}
h1{
font-family: 'TheFontName',serif;
}
</style>
<body>
<h1>Your Font, try and nick me...</h1>
<p>This is the CSS thats on this page, the font is only accessible once for this request, if you try to link it will fail:<br>
<pre>
@font-face {
font-family: 'TheFontName';
src: local('TheFontName'), url(<span style="color:green">'<?php echo SITE_URL.'/fonts.php?font=TheFontName.woff&'.$_SESSION['font_csrf_key'].'='.$_SESSION['font_csrf_token']?></span>') format('woff');
font-weight: normal;
font-style: normal;
}
body {
font-size: 110%;
}
h1{
font-family: 'TheFontName',serif;
}
</pre>
<p>Using this method, to get the font you would need to:</p>
<ol>
<li>Make a request to this page, without loading the css font. Can be done with file_get_content, curl
ect.</li>
<li>Parse the pages source and get the <?php echo $_SESSION['font_csrf_key'].'='.$_SESSION['font_csrf_token']?> keys.</li>
<li>Make a request to the font loader using the above key value pairs </li>
<li>And set the referrer in that request to: <?php echo SITE_URL; ?></li>
</ol>
<p>Perhaps its enough to stop a few people but not everyone.</p>
<p>Where there's a will, there's a way... Anything
that your browser sees can be downloaded/saved. I don't know how they can expect
you todo this, they don't offer any reliable solution because then there not
liable for loss. 99.9% of your users wont think about taking the font. Others
will find a way...</p>
<p>Good luck</p>
</body>
</html>
Теперь мы переходим к загрузчику шрифтов fonts.php, этот файл загрузит шрифт только в том случае, если значения занавеса совпадают (токены CSRF и реферер), в противном случае он отправляет пустой 404.
Пример (fonts.php)
<?php
/**
* Font loader, this file will only load the font if curtain values match
*/
session_start();
//Define script our paths
define('BASE_FOLDER', dirname($_SERVER['SCRIPT_NAME']));
define('SITE_ROOT', pathinfo($_SERVER['SCRIPT_FILENAME'], PATHINFO_DIRNAME));
define('SITE_URL', rtrim( 'http://'.$_SERVER['HTTP_HOST'].BASE_FOLDER, '/'));
//This will be checked against as the passed referer
define('SITE_HOST', parse_url(SITE_URL, PHP_URL_HOST));
if(
//Check required variables are set
// -The tokens for the request
isset($_SESSION['font_csrf_key']) &&
isset($_SESSION['font_csrf_token']) &&
// -The font you want to load
isset($_GET['font']) &&
// -The $_GET request key
isset($_GET[$_SESSION['font_csrf_key']]) &&
// -The referer
isset($_SERVER["HTTP_REFERER"])&&
// - Validate session keys with the passed token
$_GET[$_SESSION['font_csrf_key']] == $_SESSION['font_csrf_token'] &&
// - Validate the Referer
parse_url($_SERVER["HTTP_REFERER"], PHP_URL_HOST) == SITE_HOST
){
//check font exists
if(file_exists(SITE_ROOT.'/_fonts/'.basename($_GET['font']))){
//no cache
header("Cache-control: no-store, no-cache, must-revalidate");
header("Expires: Mon, 26 Jun 1997 05:00:00 GMT");
header("Pragma: no-cache");
//I think this is the right header
header("Content-Type: application/octet-stream");
set_time_limit(0);
//ok nows lets load and send the font
$font = null;
$h = fopen(SITE_ROOT.'/_fonts/'.basename($_GET['font']), 'rb');
if($h){
while ($line = fgets($h, 4096)){
$font .= $line;
}
}else{
header("HTTP/1.0 404 Not Found");
}
fclose($h);
header('Content-Length: '.strlen($font));
echo $font;
}else{
header("HTTP/1.0 404 Not Found");
}
}
else{
header("HTTP/1.0 404 Not Found");
}
//Unset to stop second access
unset($_SESSION['font_csrf_key'], $_SESSION['font_csrf_token']);
?>
Надеюсь, это поможет. загрузите исходный код здесь. Вы также можете добавить файлы cookie к защите, чтобы добавить дополнительный уровень защиты. Или даже изменить имя файла TheFontName.woff
на ключ сеанса и сохранить реальное значение имени файла в сеансе, или смешать его и добавить приманки в строку запроса, вы можете установить правильное значение или порядок в сеансе. Будьте изобретательны, но в конце концов это не пуленепробиваемый. Удачи
person
Lawrence Cherone
schedule
31.01.2014