Download the PHP package restruct/silverstripe-signed-asset-urls without Composer

On this page you can find all versions of the php package restruct/silverstripe-signed-asset-urls. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package silverstripe-signed-asset-urls

Signed Protected Asset URLs for SilverStripe

Time-expiring signed URLs for protected SilverStripe assets, similar to Amazon S3 pre-signed URLs.

Features

Configuration

Environment Variables

Add to your .env file:

SilverStripe Config

Create app/_config/signed-asset-urls.yml to override defaults:

All configuration options have sensible defaults - you typically only need to set ASSET_SIGNING_SECRET in .env to get started.

Web Server Configuration (Optional)

By default, files are served via PHP streaming. For better performance on high-traffic sites, you can enable web server file handoff using X-Sendfile (Apache) or X-Accel-Redirect (Nginx).

Environment Variable

Add to your .env file:

Nginx (X-Accel-Redirect)

How it works: PHP validates the signed URL, then sends an X-Accel-Redirect header pointing to an internal nginx location. Nginx intercepts this and serves the file directly from disk, bypassing PHP for the actual file transfer.

Setup

  1. Set ASSET_FILE_SERVER=nginx in .env

  2. Add an internal location block to your nginx server config (see examples below)

  3. Run the verification task to confirm your setup:

How the location path is determined

The module derives the location from basename(SS_PROTECTED_ASSETS_PATH):

SS_PROTECTED_ASSETS_PATH X-Accel-Redirect header Required nginx location
(not set, default .protected) /.protected/Uploads/abc123/file.pdf /.protected/
../restricted_assets /restricted_assets/Uploads/abc123/file.pdf /restricted_assets/
/var/www/project/protected_assets /protected_assets/Uploads/abc123/file.pdf /protected_assets/

The location path must match the basename exactly. A common mistake is using the wrong folder name (e.g., /protected_assets/ when the env var resolves to a folder named restricted_assets).

root vs alias

Both work, but root is recommended — it's more portable:

With root, if you rename the folder, you only change the location — not the root. With alias, you repeat the full path. Either way, the path must be absolute — nginx does not resolve ...

Common mistake — root pointing to the folder itself:

Can I reuse the server root?

No. The server { root ... } points to the public webroot (e.g., .../current/public), but protected assets live outside public/ as a sibling (e.g., .../current/restricted_assets). Nginx does not resolve .. in root/alias directives, so you need a separate absolute path.

Configuration examples

Default setup (.protected inside public/assets/):

Custom SS_PROTECTED_ASSETS_PATH (folder outside webroot):

Laravel Forge with zero-downtime deployments:

Where to place it

Add the location block after the PHP location block, at the bottom of the server { } block. Since it's internal, ordering with other locations doesn't matter — but keeping it at the bottom makes it easy to spot as a non-standard addition.

The internal directive

This makes the location only respond to X-Accel-Redirect headers from PHP. Direct browser requests to /restricted_assets/... return 404. Without internal, anyone could bypass the signed URL check by requesting the path directly.

Apache (X-Sendfile)

  1. Install and enable mod_xsendfile:

  2. Set ASSET_FILE_SERVER=apache in .env

  3. Add to your Apache config or .htaccess:

    Default setup:

    Custom setup (using SS_PROTECTED_ASSETS_PATH):

  4. Run the verification task to get your exact configuration:

How it works: PHP validates the signed URL, then sends an X-Sendfile header with the absolute file path. Apache serves the file directly, bypassing PHP for the actual file transfer.

Performance Considerations

Method Pros Cons
PHP (default) No server config needed, works everywhere Higher memory usage, slower for large files
Nginx Very fast, low memory Requires nginx config access
Apache Fast, works with .htaccess Requires mod_xsendfile installation

For most sites, PHP streaming is sufficient. Consider web server handoff if you:

Usage

In PHP

In Templates

Available Methods

Method Description
$File.SignedURL Signed URL with default TTL (returns normal URL for public files)
$File.SignedURL(ttl) Signed URL with custom TTL in seconds
$File.SignedURL(ttl, bindToSession) Signed URL with TTL and session binding
$File.AutoURL Same as SignedURL (auto-detects if signing needed)
$File.AutoURL('policy') Signed URL using named policy (e.g., 'ss', 'm')
$File.AutoURL(ttl) Signed URL with custom TTL in seconds
$File.RequiresSignedURL Boolean: true if file is protected

Policies

Named policies provide convenient presets for TTL and session binding. Use them in templates for cleaner, more maintainable code.

Built-in Policies

Policy TTL Session-bound Use case
ss 30 sec Yes Highly sensitive, immediate use only
s 30 sec No Shareable but very short-lived
ms 1 hour Yes Sensitive documents, single-user access
m 1 hour No General protected content, shareable
ls 24 hours Yes Long-lived user-specific access
l 24 hours No Long-lived shareable links

Custom Policies

Define your own policies in YAML config:

Usage:

URL Formats

Generated URLs use S3-style query parameters for clean, readable paths:

Examples:

This format keeps the asset path readable (like S3 pre-signed URLs) while signature parameters are in the query string.

Session Binding

When bind_to_session is enabled (globally or per-URL), the signed URL includes a hash of the user's session. This means:

The session token is derived from PHP's session ID using HMAC, so the actual session ID is never exposed in the URL.

How It Works

  1. URL Generation: PHP generates a signed URL with HMAC hash and expiry timestamp
  2. Request: User requests the signed URL
  3. Validation: Controller validates hash and checks expiry
  4. Session Check: If URL is session-bound, validates against current session
  5. Admin Check: If user has CMS access, signature validation is bypassed
  6. Serving: File is streamed via SilverStripe's AssetStore (handles hash-based paths automatically)

Browser & Page Caching

Automatic Cache Header Management

By default, this module automatically adjusts the page's Cache-Control headers to prevent browsers from caching the page longer than the shortest-lived signed URL it contains.

How it works:

  1. Middleware tracks the earliest expiry time of all signed URLs generated during a request
  2. Before sending the response, it adjusts Cache-Control: max-age to not exceed that expiry
  3. Also sets an Expires header for older HTTP caches

Configuration:

Example: If you generate a signed URL with 1-hour TTL, the page response will include:

This ensures browsers won't serve a cached page with expired signed URLs.

Disabling Auto Cache Headers

If you manage cache headers yourself or use a CDN with custom rules:

Partial Caching (Template Layer)

When using SilverStripe's partial caching (<% cached %>), signed URLs require special consideration because they contain expiration timestamps. Note that auto cache headers (above) handle browser caching, while this section covers server-side template caching.

The Problem

If your cache lives longer than the signed URL's TTL, users will get expired links.

Solutions

1. Include TTL window in cache key:

2. Set cache lifetime shorter than TTL:

3. Exclude signed URLs from cached blocks:

4. Use session-bound URLs with uncached blocks:

Cache Key Helpers

You can create a helper method for time-windowed cache keys:

Session-Bound URLs and Caching

Never cache session-bound URLs - they are unique per user session:

Protected Assets & Versioned Staging

SilverStripe's asset system stores files in either a public or protected folder based on:

This module respects both protection mechanisms.

How Protection Works

Protection is checked at two levels:

1. URL Generation (Extension)

When you call $file->SignedURL(), the extension checks if the file needs a signed URL:

This uses SilverStripe's built-in hasRestrictedAccess() method which handles CanViewType checking including parent folder inheritance.

2. URL Serving (Controller)

When a signed URL is accessed, the controller validates:

  1. Signature validity: HMAC hash matches and hasn't expired
  2. Session binding: If URL is session-bound, validates current session
  3. Published status (optional): If check_published_status is enabled, denies access to unpublished files

CMS users with bypass_permissions can always access any file.

Projects with staging disabled (on File assets)

If your project uses versioning only (no draft/live staging):

In this case:

Security Considerations

Development & Testing

Verification Task

A BuildTask is included to verify your configuration and test URL generation/validation:

This task will:

  1. Check that ASSET_SIGNING_SECRET is configured
  2. Show the protected folder path and whether it exists
  3. Display current configuration values (TTL, session binding, cache headers)
  4. Generate a test signed URL and validate its components
  5. Test signature validation (valid, invalid, and expired cases)
  6. Test session-bound URL generation

Example output:

Manual Testing Checklist

After making changes to the controller or signing service, verify the following:

1. Build and config verification

Both should complete without errors. The verify task checks signing secret, protected folder path, URL generation, and signature validation (valid, invalid, expired).

2. Signature validation (curl)

Test that invalid signatures are rejected:

3. File serving (browser)

Load a page that renders signed asset URLs (e.g. a page with protected images or download links). Verify:

4. File path resolution

The controller uses framework-based file resolution (resolveFilePath()) which handles both hash-based paths (Uploads/abc1234567/file.pdf) and natural paths (Uploads/file.pdf). To verify resolution works for a specific file:

The signed URL for that file should work regardless of which layout exists on disk.

5. Web server handoff (if configured)

If ASSET_FILE_SERVER is set to apache or nginx:

What is NOT covered by automated tests

This module has no PHPUnit tests. The resolveFilePath() method requires a fully bootstrapped SilverStripe environment with actual filesystem adapters, making unit testing impractical without integration test infrastructure. All testing is manual via the checklist above and the SignedAssetUrlVerifyTask.


All versions of silverstripe-signed-asset-urls with dependencies

PHP Build Version
Package Version
Requires silverstripe/framework Version ^5.0
silverstripe/assets Version ^2.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package restruct/silverstripe-signed-asset-urls contains the following files

Loading the files please wait ...