Skip to content

Instantly share code, notes, and snippets.

@phluzern
Created October 8, 2013 16:45
Show Gist options
  • Save phluzern/6887641 to your computer and use it in GitHub Desktop.
Save phluzern/6887641 to your computer and use it in GitHub Desktop.
Secure downloads for TYPO3 Flow The idea behind the feature is that resistent resources are bound to a user session. As long as a user session is valid, a resource is published and therefore downloadable, once the user is logged out, the file is no longer available.
# Use an own publishing configuration
TYPO3\Flow\Resource\Publishing\ResourcePublishingTargetInterface:
className: Venodor\Package\Resource\Publishing\SecureFileSystemPublishingTarget
<?php
namespace Vendor\Package\Resource\Publishing;
/* *
* This script belongs to the TYPO3 Flow framework. *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow;
/**
* Publishing target for a file system.
*
* @Flow\Scope("singleton")
*/
class SecureFileSystemPublishingTarget extends \TYPO3\Flow\Resource\Publishing\FileSystemPublishingTarget {
/**
* @var \TYPO3\Flow\Session\SessionInterface
* @Flow\Inject
*/
protected $session;
/**
* Returns the web URI to be used to publish the specified persistent resource
*
* @param \TYPO3\Flow\Resource\Resource $resource The resource to build the URI for
* @return string The web URI
*/
protected function buildPersistentResourceWebUri(\TYPO3\Flow\Resource\Resource $resource) {
$filename = $resource->getFilename();
// check if the session already contains a secureDownloadToken
if (!$this->session->hasKey('secureDownloadToken')) {
// if not, generate one and store it in the session
$randomToken = \TYPO3\Flow\Utility\Algorithms::generateRandomToken(20);
$this->session->putData('secureDownloadToken', $randomToken);
}
$rewrittenFilename = ($filename === '' || $filename === NULL) ? '' : '/' . $this->rewriteFilenameForUri($filename);
// add the secure download token to the uri
return $this->getResourcesBaseUri() . 'Persistent/' . $this->session->getData('secureDownloadToken') . '/' . $resource->getResourcePointer()->getHash() . $rewrittenFilename;
}
/**
* Returns the publish path and filename to be used to publish the specified persistent resource
*
* @param \TYPO3\Flow\Resource\Resource $resource The resource to build the publish path and filename for
* @param boolean $returnFilename FALSE if only the directory without the filename should be returned
* @return string The publish path and filename
*/
protected function buildPersistentResourcePublishPathAndFilename(\TYPO3\Flow\Resource\Resource $resource, $returnFilename) {
if (!$this->session->hasKey('secureDownloadToken')) {
$randomToken = \TYPO3\Flow\Utility\Algorithms::generateRandomToken(20);
$this->session->putData('secureDownloadToken', $randomToken);
}
// add the secure download token to the path
$publishPath = $this->resourcesPublishingPath . 'Persistent/' . $this->session->getData('secureDownloadToken') . '/';
if (!is_dir($publishPath)) {
\TYPO3\Flow\Utility\Files::createDirectoryRecursively($publishPath);
}
if ($returnFilename === TRUE) return $publishPath . $resource->getResourcePointer()->getHash() . '.' . $resource->getFileExtension();
return $publishPath;
}
}
?>
<?php
namespace Vendor\Package\Resource\Publishing;
use TYPO3\Flow\Annotations as Flow;
/**
* @Flow\Aspect
*/
class SessionAspect {
/**
* @Flow\Inject
* @var \TYPO3\Flow\Session\SessionInterface
*/
protected $session;
/**
* Remove private persistent resources on garbage collection
*
* @param \TYPO3\Flow\AOP\JoinPointInterface $joinPoint
* @Flow\Before("method(TYPO3\Flow\Session\Session->destroy())")
* @return void
*/
public function removePrivatePersistentResources(\TYPO3\Flow\AOP\JoinPointInterface $joinPoint) {
if ($this->session->hasKey('secureDownloadToken')) {
// if we have a secure download token in the session...
$directory = FLOW_PATH_WEB . '_Resources/Persistent/' . $this->session->getData('secureDownloadToken') . '/';
if (is_dir($directory)) {
// ... and we have a folder name like it, delete it on destroying the session
\TYPO3\Flow\Utility\Files::removeDirectoryRecursively($directory);
}
}
}
}
?>
Vendor:
Package:
resource:
publishing:
# If enabled, the publisher will check if the static resources of active packages
# have changed and if so publishes them again. If disabled, static package resources
# are only published once and changes are unnoticed until the related cache is flushed.
detectPackageResourceChanges: FALSE
# Options for the File System publishing target
fileSystem:
# Strategy for mirroring files: Either "copy" or "link"
mirrorMode: link
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment