Skip to content

Commit bb7ae5c

Browse files
authored
Improve security component and fix/enhance readme (#7)
* Fix README * Harden and enhance configurability of security component and add documentation for it
1 parent cb7ac09 commit bb7ae5c

File tree

2 files changed

+118
-48
lines changed

2 files changed

+118
-48
lines changed

README.md

Lines changed: 99 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
#CakePHP 3 cake-cktools
1+
# CakePHP 3 cake-cktools
22

33
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.txt)
44

5-
##Requirements
5+
## Requirements
66

77
- [cake-frontend-bridge](https://github.com/scherersoftware/cake-frontend-bridge) for easy js-based interaction with the backend
88
- [Font Awesome](https://fortawesome.github.io/Font-Awesome/) for icons
99

10-
##Installation
10+
## Installation
1111

12-
####1. require the plugin in your `composer.json`
12+
#### 1. require the plugin in your `composer.json`
1313
```
1414
"require": {
1515
"codekanzlei/cake-cktools": "dev-master"
@@ -19,7 +19,7 @@ Open a terminal in your project-folder and run these commands:
1919

2020
$ composer update
2121

22-
####2. Configure `config/bootstrap.php`
22+
#### 2. Configure `config/bootstrap.php`
2323
```
2424
Plugin::load('CkTools', ['bootstrap' => false, 'routes' => true]);
2525
@@ -29,7 +29,7 @@ Configure::load('CkTools.currencies');
2929
Type::map('json', 'CkTools\Database\Type\JsonType');
3030
```
3131

32-
####4. Setup Appcontroller.php
32+
#### 3. Setup Appcontroller.php
3333

3434
**`$helpers`**
3535

@@ -52,9 +52,9 @@ public $components = [
5252
]
5353
```
5454

55-
##Usage
55+
## Usage
5656

57-
###1. CkToolsHelper
57+
### 1. CkToolsHelper
5858

5959
Being one of CkTools' core features, CkToolsHelper provides many useful functionalities, most of them aimed at generating powerful view elements such as form- and navigation buttons, often with as much as one line of code. Here's an overview of its actions. See `CkToolsHelper.php` for further details.
6060

@@ -75,11 +75,11 @@ Creates a mailto link to the email address given in `$email`. `$options` include
7575
@return string
7676

7777
- `editButton(EntityInterface $entity, array $options = [])`
78-
Renders an edit button for given database record `$entity`. By defailt, this button will link to the entity's Controller's edit action but this can be overwritten using the `'url'` field of the `$options` array.
78+
Renders an edit button for given database record `$entity`. By default, this button will link to the entity's Controller's edit action but this can be overwritten using the `'url'` field of the `$options` array.
7979
@return string
8080

8181
- `viewButton(EntityInterface $entity, array $options = [])`
82-
Renders a details button for given database record `$entity`. By defailt, this button will link to the entity's Controller's view action but this can be overwritten using the `'url'` field of the `$options` array.
82+
Renders a details button for given database record `$entity`. By default, this button will link to the entity's Controller's view action but this can be overwritten using the `'url'` field of the `$options` array.
8383
@return string
8484

8585
- `addButton($title = null, array $options = [])`
@@ -111,7 +111,7 @@ Renders a nested list. The param `$data` holds the data to be displayed in assoc
111111
@return string
112112

113113
- `historyBackButton(array $options = [])`
114-
Renders a div with an onclick-hanlder which uses the history API of the Browser.
114+
Renders a div with an onclick handler which uses the history API of the Browser.
115115
@return string
116116

117117
- `displayStructuredData(array $data, array $options = [])`
@@ -122,7 +122,7 @@ Display an array in human-readable format. The `'$options'` array includes a fie
122122
Rercursively converts an array to an unordered list.
123123
@return string
124124

125-
###2. MenuHelper
125+
### 2. MenuHelper
126126

127127
The MenuHelper aims at config-based rendering of hierarchical navigation menus in the UI. Here's an overview of its actions. See `MenuHelper.php` for further details.
128128

@@ -144,7 +144,7 @@ Uses CakePHP's AuthComponent to check if given array of items 'children' contain
144144
Compares the current URL with given menu item to determine wether it should be highlighted or not.
145145
@return bool
146146

147-
####`config.php` - a closer look
147+
#### `config.php` - a closer look
148148
Here's an example of what `config.php` could look like, explaining more possibilities:
149149

150150
```
@@ -181,23 +181,23 @@ $config = [
181181
'action' => 'actionBar'
182182
]
183183
],
184-
// furhter sub-items for menu item 'examples'
184+
// further sub-items for menu item 'examples'
185185
]
186186
],
187-
// furter menu items
187+
// further menu items
188188
```
189189

190-
##Manage files with TinyMCE and Moxiemanager
190+
## Manage files with TinyMCE and Moxiemanager
191191
Moxiemanager is a powerful media manager which can be used in combination with the web-based JavaScript editor TinyMCE. CkTools provides a CakePHP-friendly integration for these features.
192192
Get them here:
193193

194-
- [Moxiemanager](http://www.moxiemanager.com/getit/) - Note that you need to purchase a licence
194+
- [Moxiemanager](http://www.moxiemanager.com/getit/) - Note that you need to purchase a license
195195
- [TinyMCE](https://www.tinymce.com/download/)
196196

197-
###Setting up TinyMceHelper using Cake Frontend Bridge
197+
### Setting up TinyMceHelper using Cake Frontend Bridge
198198
We strongly suggest to use our [Cake Frontend Bridge Plugin](https://github.com/scherersoftware/cake-frontend-bridge) to make using TinyMCE and MoxieManager as convenient as possible. Here's how to setup these features in your project using the Frontend Bridge.
199199

200-
####app.php
200+
#### app.php
201201
```
202202
'CkTools' => [
203203
'moxiemanager' => [
@@ -208,7 +208,7 @@ We strongly suggest to use our [Cake Frontend Bridge Plugin](https://github.com/
208208
]
209209
```
210210

211-
####Appcontroller.php
211+
#### Appcontroller.php
212212
**`$helpers`**
213213

214214
```
@@ -217,7 +217,7 @@ public $helpers = [
217217
]
218218
```
219219

220-
####app_controller.js (using Frontend Bridge)
220+
#### app_controller.js (using Frontend Bridge)
221221

222222
If you choose to use the Frontend Bridge Plugin, here's how to configure it in a way that makes using MoxiePicker in a View file super easy. Of course, using another kind of PageController is possible as well.
223223

@@ -245,7 +245,7 @@ this.TinyMce.setConfig({
245245
});
246246
```
247247

248-
####view.ctp
248+
#### view.ctp
249249

250250
The TinyMce helper provides a wrapper for FormHelper::input() and will generate an input field with a button to choose a file from Moxiemanager. The relative path of the chosen file will be set as the value of the text field.
251251

@@ -261,13 +261,13 @@ Add an input element using MoxiePicker:
261261
$this->TinyMce->picker('field_name', ['label' => 'My File Picker']);
262262
```
263263

264-
##Set up an API with ApiComponent
264+
## Set up an API with ApiComponent
265265

266266
You can create a plugin, e.g. "Api" to include all your API controller code. Using an API greatly simplifies backend-communication using JavaScript. If you have an Api plugin, make sure you set 'bootstrap' => true when loading the plugin in your bootstrap.
267267

268268
Use the following configuration to make sure errors in the api are always returned as JSON.
269269

270-
####bootstrap.php
270+
#### bootstrap.php
271271

272272
```
273273
if (substr(env('REQUEST_URI'), 0, 5) === '/api/') {
@@ -278,7 +278,7 @@ if (substr(env('REQUEST_URI'), 0, 5) === '/api/') {
278278
}
279279
```
280280

281-
####AppController.php
281+
#### AppController.php
282282

283283
**`initialize()`**
284284

@@ -294,7 +294,7 @@ $this->Api->setup();
294294
```
295295

296296
**`ApiComponent.php`:**
297-
This class provides the **`response()`** action which you can use to create and send custom JSON responses. It requires the folloling parameters:
297+
This class provides the **`response()`** action which you can use to create and send custom JSON responses. It requires the following parameters:
298298

299299
- `$returnCode = ApiReturnCode::SUCCESS`: Return code
300300
- `$array $data`: Data for the `'data'` key of the response
@@ -320,11 +320,11 @@ This call will return an `application/json` response with the HTTP Status Code `
320320
{"code": "success","data":{"hello":"world"}}
321321
```
322322

323-
##Create a PDF using CakePHP Views
323+
## Create a PDF using CakePHP Views
324324

325325
CkTools includes a simple wrapper for the [MPDF library](http://www.mpdf1.com/mpdf/index.php). For detailed instructions on how to use it, see the github repository here: [https://github.com/mpdf/mpdf](https://github.com/mpdf/mpdf)
326326

327-
####Usage
327+
#### Usage
328328
Here's an example use in a Cake Controller but you can use this feature wherever you want. See `/cake-cktools/src/Lib/PdfGenerator.php` for a closer look at the functionalities used.
329329

330330
```
@@ -362,7 +362,7 @@ $mpdf->WriteHTML("This is page 2");
362362
```
363363

364364
## Sort table fields with SortableBehavior
365-
CkTools provides a behavior that allows manipulation of the (displayed) order of the records of a table. If you change the position of one field, the behavior will automatically change all the other fields' positions accordingly. To manipulate the positions you can use an ordinary form field or for example the Cake Frontend Bridge to enable js-based drag-and-drop interaction in the browser UI.
365+
CkTools provides a behavior that allows manipulation of the (displayed) order of the records of a table. If you change the position of one field, the behavior will automatically change all the other fields' positions accordingly. To manipulate the positions you can use an ordinary form field or for example the Cake Frontend Bridge to enable JavaScript-based drag-and-drop interaction in the browser UI.
366366

367367
## Strict Passwords with StrictPasswordBehavior
368368
Activate the strict password requirements by setting the StrictPasswordBehavior in UsersTable; default Configuration is set in this example
@@ -387,7 +387,7 @@ $this->addBehavior('CkTools.StrictPassword', [
387387

388388

389389

390-
####Usage
390+
#### Usage
391391
Add the SortableBehavior to the Table you want to use it in:
392392

393393
```
@@ -408,10 +408,10 @@ Here's what the table field you wish to allow sorting by could look like in Cake
408408
'sort' => ['type' => 'integer', 'length' => 6, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null],
409409
```
410410

411-
##Manipulate database records with TableUtilitiesTrait
411+
## Manipulate database records with TableUtilitiesTrait
412412
The TableUtilitiesTrait contains an action that allows for manually updating the value of a field in a table. Using `updateField()` bypasses cake validation and patching of the object. The given value is directly written to the database via a SQL query.
413413

414-
####Setting up a Model
414+
#### Setting up a Model
415415
Add the Trait in **`YourTable.php`**:
416416

417417
```
@@ -432,10 +432,10 @@ Now you can use the `updateField()` action to directly manipulate a record. Let'
432432
- `$field`: the name of the field you want to change
433433
- `$value = null`: the new value you want to save to the database
434434

435-
##Handle type constants with TypeAwareTrait
436-
Entities with type constants can be very useful, for example if you wish to grant different rights to different kinds of users such as Admins, regular Users, External users etc. With CkTools' TypeAwareTrait, setting up and using such constants becames fast and simple.
435+
## Handle type constants with TypeAwareTrait
436+
Entities with type constants can be very useful, for example if you wish to grant different rights to different kinds of users such as Admins, regular Users, External users etc. With CkTools' TypeAwareTrait, setting up and using such constants becomes fast and simple.
437437

438-
####Setting up a Model:
438+
#### Setting up a Model:
439439
Let's prepare an example use case where you want to assign different roles to different groups of users in your application. Set up your **User.php** like so:
440440

441441
```
@@ -494,10 +494,10 @@ Example: in a Cake View file for Model **Cars**:
494494
<?php endif; ?>
495495
```
496496

497-
##Identify users with UserToken
497+
## Identify users with UserToken
498498
CkTools provides a utility class that generates serialized, encrypted and base64-encoded for identifying users, usually for usage in an URL. This is very handy for 'forgot password' links so if you have a LoginController, using UserToken there is most advisable.
499499

500-
####Usage
500+
#### Usage
501501
Here's how to use **UserToken** in any class you like:
502502

503503
```
@@ -528,20 +528,20 @@ decrypts given token and only returns the encrypted user_id.
528528

529529
See `cake-cktools/src/Utility/UserToken.php` for further information about these actions.
530530

531-
##I18nShell
531+
## I18nShell
532532

533533
CkTools provides a helper shell for i18n related tasks.
534534

535-
###Update .po and .mo files from catalog
535+
### Update .po and .mo files from catalog
536536

537537
To automate the updating of .po/.mo files from available translation strings from the catalog (.pot) file, use the `updateFromCatalog` command.
538538

539539
This is done using the excellent [oscarotero/Gettext](https://github.com/oscarotero/Gettext) library.
540540

541-
Example usage:
541+
#### Usage
542542

543543
1. Update all default.po and default.mo files found in `src/Locale/*` with translation strings from `src/Locale/default.pot`. The shell will list the files it will touch and asks for confirmation.
544-
544+
545545
bin/cake CkTools.I18n updateFromCatalog
546546

547547
2. Update all default.po and default.mo files found in `src/Locale/*` with translation strings from `src/Locale/default.pot`. The shell will overwrite files without interaction.
@@ -551,7 +551,62 @@ Example usage:
551551
3. Update all default.po and default.mo files found in `src/Locale/*` with translation strings from `src/Locale/default.pot`. The shell will overwrite files without interaction. Also, it will strip all references, meaning the filenames and lines where the translation was used from the resulting .po and .mo files.
552552

553553
bin/cake CkTools.I18n updateFromCatalog --overwrite --strip-references
554-
554+
555555
4. Update all cake.po and cake.mo files found in `src/Locale/*` with translation strings from `src/Locale/default.pot`. The shell will list the files it will touch and asks for confirmation.
556-
557-
bin/cake CkTools.I18n updateFromCatalog --domain cake
556+
557+
bin/cake CkTools.I18n updateFromCatalog --domain cake
558+
559+
## SecurityComponent
560+
561+
CkTools provides a component to set multiple security enhancing headers.
562+
563+
### Security headers
564+
565+
Loading the `SecurityComponent` in your AppController, the Component will hook into the beforeFilter event and by default set the
566+
- `X-XSS-Protection` header to `1; mode=block`
567+
- `X-Content-Type-Options` header to `nosniff`
568+
569+
At the moment these two headers are neither configurable nor can you deactivate them, as they seem to be reasonable in every case.
570+
571+
Furthermore, you can configure multiple additional headers in your `app.php`.
572+
573+
#### Usage
574+
575+
Here is how a complete configuration of all additional security headers could look like in your `app.php`:
576+
577+
```
578+
'CkTools' => [
579+
'Security' => [
580+
// Strict-Transport-Security header
581+
'HSTS' => 'max-age=31536000; includeSubDomains',
582+
583+
// Content-Security-Policy, you could set a string like so
584+
'CSP' => "img-src 'self' blob: data:; default-src 'self' https:;"
585+
586+
// or if it gets to long, as array
587+
'CSP' => [
588+
'font-src' => "'self' data:",
589+
'frame-ancestors' => "'self'",
590+
'connect-src' => "'self'",
591+
'img-src' => [
592+
"'self'",
593+
'blob:',
594+
'data:',
595+
'https://*.some-domain.com',
596+
],
597+
'default-src' => [
598+
"'self'",
599+
'https:',
600+
'blob:'
601+
]
602+
],
603+
604+
// bool config value to set X-Frame-Options header to "DENY" if true
605+
'denyFraming' => true
606+
]
607+
],
608+
```
609+
610+
The X-Frame-Options header set by 'denyFraming' is superceded by the Content Security Policy's frame-ancestors directive, but as frame-ancestors is not yet supported in IE11 and older, Edge, Safari 9.1 (desktop), and Safari 9.2 (iOS), it is recommended that sites employ X-Frame-Options in addition to using CSP.
611+
612+
If you wish to exclude any header, simply set its value to something falsy or omit the array key completely.

src/Controller/Component/SecurityComponent.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,28 @@ class SecurityComponent extends Component
1818
public function beforeFilter(Event $event)
1919
{
2020
$securityConfig = Configure::read('CkTools.Security');
21-
if ($securityConfig['HSTS']) {
21+
if (isset($securityConfig['HSTS']) && $securityConfig['HSTS']) {
2222
$this->response->header('Strict-Transport-Security', $securityConfig['HSTS']);
2323
}
24-
if ($securityConfig['CSP']) {
25-
$this->response->header('Content-Security-Policy', $securityConfig['CSP']);
24+
if (isset($securityConfig['CSP']) && $securityConfig['CSP']) {
25+
$headerValue = '';
26+
if (is_string($securityConfig['CSP'])) {
27+
$headerValue = $securityConfig['CSP'];
28+
}
29+
if (is_array($securityConfig['CSP'])) {
30+
foreach ($securityConfig['CSP'] as $area => $allowed) {
31+
if (is_array($allowed)) {
32+
$allowed = implode(' ', $allowed);
33+
}
34+
$headerValue .= $area . ' ' . $allowed . ';';
35+
}
36+
}
37+
38+
if (!empty($headerValue)) {
39+
$this->response->header('Content-Security-Policy', $headerValue);
40+
}
2641
}
27-
if ($securityConfig['denyFraming']) {
42+
if (isset($securityConfig['denyFraming']) && $securityConfig['denyFraming'] === true) {
2843
// Superceded by the Content Security Policy's frame-ancestors directive, but as frame-ancestors
2944
// is not yet supported in IE11 and older, Edge, Safari 9.1 (desktop), and Safari 9.2 (iOS),
3045
// it is recommended that sites employ X-Frame-Options in addition to using CSP.

0 commit comments

Comments
 (0)