Secure Controller
SecureController extends BaseController and automatically applies security headers to all controller methods. Controllers should extend SecureController when handling sensitive operations or user data to ensure comprehensive security protection without manual header configuration.
Using SecureController
Extend SecureController in your controller classes to automatically apply security headers to all responses:
<?php
namespace App\Controllers;
use Quellabs\Canvas\Controllers\SecureController;
use Quellabs\Canvas\Annotations\Route;
use Symfony\Component\HttpFoundation\Response;
class AdminController extends SecureController {
/**
* @Route("/admin/dashboard")
*/
public function dashboard(): Response {
// All security headers are automatically applied
return $this->render('admin/dashboard.tpl');
}
}
Automatic Security Headers
The following headers are automatically added to all responses. If a header is already set in your controller method, SecureController will not override it, allowing for custom configurations when needed.
| Header | Value | Protection |
|---|---|---|
X-Frame-Options |
SAMEORIGIN |
Prevents clickjacking by disallowing framing from external sites |
X-Content-Type-Options |
nosniff |
Prevents MIME-type sniffing attacks |
X-XSS-Protection |
1; mode=block |
Enables browser XSS filtering and blocks detected attacks |
Strict-Transport-Security |
max-age=31536000; includeSubDomains(HTTPS only) |
Forces HTTPS connections for 1 year, including all subdomains |
Referrer-Policy |
strict-origin-when-cross-origin |
Controls referrer information sent with requests |
Default Configuration
SecureController uses SecurityHeadersAspect with the following default settings:
| Setting | Default Value | Description |
|---|---|---|
frameOptions |
SAMEORIGIN |
Can be DENY, SAMEORIGIN, or ALLOW-FROM |
noSniff |
true |
Enable X-Content-Type-Options header |
xssProtection |
true |
Enable X-XSS-Protection header |
hstsMaxAge |
31536000 |
HSTS duration in seconds (1 year) |
hstsIncludeSubdomains |
true |
Apply HSTS to all subdomains |
referrerPolicy |
strict-origin-when-cross-origin |
Referrer information policy |
csp |
null |
Content-Security-Policy (disabled by default) |
Customizing Security Headers
To customize security headers for specific controllers, apply the @InterceptWith annotation directly with custom settings:
<?php
namespace App\Controllers;
use Quellabs\Canvas\Controllers\BaseController;
use Quellabs\Canvas\Annotations\InterceptWith;
use Quellabs\Canvas\Security\SecurityHeadersAspect;
use Quellabs\Canvas\Annotations\Route;
use Symfony\Component\HttpFoundation\Response;
/**
* @InterceptWith(
* SecurityHeadersAspect::class,
* frameOptions="DENY",
* csp="default-src 'self'; script-src 'self' 'unsafe-inline'"
* )
*/
class StrictSecurityController extends BaseController {
/**
* @Route("/secure/page")
*/
public function securePage(): Response {
// Uses custom security headers
return $this->render('secure/page.tpl');
}
}
For per-method customization, apply the annotation to individual methods:
<?php
namespace App\Controllers;
use Quellabs\Canvas\Controllers\SecureController;
use Quellabs\Canvas\Annotations\InterceptWith;
use Quellabs\Canvas\Security\SecurityHeadersAspect;
use Quellabs\Canvas\Annotations\Route;
use Symfony\Component\HttpFoundation\Response;
class ApiController extends SecureController {
/**
* @Route("/api/data")
* @InterceptWith(
* SecurityHeadersAspect::class,
* frameOptions="DENY",
* referrerPolicy="no-referrer"
* )
*/
public function getData(): Response {
// This method uses stricter security than other methods
return $this->json(['data' => 'sensitive']);
}
}
Inherited Helper Methods
SecureController extends BaseController, providing access to all convenience methods:
| Method | Description | Example |
|---|---|---|
render($template, $data, $status) |
Render a template and return Response | $this->render('admin/users.tpl', ['users' => $users]) |
json($data, $status) |
Return JSON response | $this->json(['success' => true]) |
text($text, $status) |
Return plain text response | $this->text('Operation complete') |
redirect($url, $status) |
Redirect to another URL | $this->redirect('/admin/login') |
notFound($message, $status) |
Return 404 response | $this->notFound('Resource not found') |
forbidden($message, $status) |
Return 403 response | $this->forbidden('Insufficient permissions') |
em() |
Get EntityManager instance | $this->em()->findAll(User::class) |
view() |
Get template engine instance | $this->view()->render('partial.tpl') |
service($className) |
Get any service from container | $this->service(CacheInterface::class) |