How to protect webfonts?

家住魔仙堡 提交于 2021-01-19 06:42:47

问题


my client has bought a font which I would like to use on his website, but the company which made the font(Adobe) told me, that there is no webfont service for this current font and I can use it on a website only if I rasterize it or make it impossible to download/steal the font in any other way.

Therefore, the question is:

Is there any reliable way to protect webfonts?

(second, optional part)

Is there any way that is generally considered to be enough so its legally safe to use the font?

What I learned so far:

1) I heard about Cufon, which uses SVG files, which are(according to w3.org) intended for this purpose:

The purpose of SVG fonts is to allow for delivery of glyph outlines in display-only environments. SVG fonts that accompany Web pages must be supported only in browsing and viewing situations. Graphics editing applications or file translation tools must not attempt to convert SVG fonts into system fonts. The intent is that SVG files be interchangeable between two content creators, but not the SVG fonts that might accompany these SVG files. Instead, each content creator will need to license the given font before being able to successfully edit the SVG file.

But I also saw few online converters from SVG to normal font formats(havent really tried them).

2) I also saw this thread, which says its not completely possible, but its two years old, maybe the technologies have advanced.: How to protect WebFonts

3) I also believe the PDF has some way to make it impossible to extract font, few years ago I saw PDF from which I couldnt extract the text(even with use of 3rd party tools) because there were deliberately messed font tables inside so I had to render the whole document to image and use OCR. However, this might not be the case since I was trying to extract the text and not the font.

4) Font selling companies have to protect their fonts somehow (?)


回答1:


Fundamentally, if you're going to use the font without using images (which is a horrible practice and should be avoided if you're talking about more than a few characters on the page!) you cannot stop people from reverse engineering your fonts. For instance, processing them as SVG to canvas (or SVG to VML) as Cufon does will force users to do some work if they want to steal it, but there are plenty of SVG->TFF converters out there.

Even without a converter you could still create a new font set based on the vectors defined by SVG. The only way to prevent this is to not provide any vector-based font system (i.e. use bitmaps), but that basically destroys the accessibility of your site. And even then, if you've written a dynamic system for serving image-based fonts, if you let the user have a sufficiently high resolution bitmap of the image (i.e. server a large font), there are scripts available that will convert outlines to vectors.

Font-selling companies (at least the ones I've seen) all serve only image-based versions of their fonts for previews, and cap the maximum size of the font that you can demo.




回答2:


Perhaps you could use a basic CSRF approach and only load the font once per request, creating session keys that expire after one use and checking the referrer (which could possibly break if user is emptying there's on subsequent requests).

But for something todo ;p I've put together an example of what I mean, its not 100%, but it will stop the general public from trying to directly access the font. download the source example

Using this method, to get the font you would need to:

  1. Make a request to the page, without loading the css font. (fgc,curl,ect)
  2. Parse the pages source and get the keys from the CSS.
  3. Then make a custom request to the font loader, setting the referrer and using the key value pairs.

    • Perhaps it will pass there expectations of protection.

The CSS, what you can do is instead of pointing the path to the font, use PHP to load the font, this way you can add some nonce's to the query.

@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;
}

Example (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>

Now we move onto the fonts.php font loader, this file will only load the font if curtain values match (CSRF tokens and referrer), else it sends a blank 404.

Example (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']);
?>

Hope it helps, download the example source here. You could also add cookies to the protection to add that extra layer of protection. Or even change the filename TheFontName.woff to a session key and store the real value of the filename in session, or mix it up and add decoys in the query string, you can set which is right value or order in session. Be creative, But in the end its not bullet proof. Good Luck




回答3:


There is no way to prevent fonts from being reverse-encoded to whatever format. There are copyright informations inside some formats like TTF, but the online converters are free to ignore them.

You can, however, make the font relatively impractical to use, i.e. make it loose its appeal for potential hackers.

For instance, you can reduce it to a subset of the real glyphs, if you know your page won't use some characters. I don't mean splitting a font into sub-parts. I mean not providing any glyph that is not used on your site. For instance, if your site is in English, strip all the diacritics or non-latin charsets.

Also, some refined informations like kerning and hinting are lost when using some formats (SVG fonts are bare glyphs, for instance). Reverse-encoding them to TTF would yield a poor man's version of the original font.

On the other hand, SVG output is pretty poor for small font sizes. Using SVG will likely hurt your site before hurting the thieves.




回答4:


There is probably no legally safe way to do this, as even a stripped down version of the font will still contain copyrighted information, and any other protection measure can be circumvented.

If a font is not offered with an explicit web license with less oppressive terms, better not use it on the web, except in the form of rasterized images. Period.

I would see whether services like Google Fonts offer a font similar enough in appearance.

You can also shop around to see whether a different font licensor provides a web license for the same, or at least a similar-looking font. A font identifier like Identifont can help you find similar ones.



来源:https://stackoverflow.com/questions/21470085/how-to-protect-webfonts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!