Skip to content

Commit f15ddf1

Browse files
author
Joan He
committed
Merge remote-tracking branch 'origin/MAGETWO-16192-x-frame-opt' into develop
2 parents ed464ca + abaf8e7 commit f15ddf1

File tree

11 files changed

+145
-11
lines changed

11 files changed

+145
-11
lines changed

.htaccess

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,6 @@
6565
SecFilterScanPOST Off
6666
</IfModule>
6767

68-
<IfModule mod_headers.c>
69-
############################################
70-
## prevent clickjacking
71-
72-
Header set X-Frame-Options SAMEORIGIN
73-
</IfModule>
74-
7568
<IfModule mod_deflate.c>
7669

7770
############################################
@@ -187,4 +180,4 @@
187180
## If running in cluster environment, uncomment this
188181
## http://developer.yahoo.com/performance/rules.html#etags
189182

190-
#FileETag none
183+
#FileETag none

app/code/Magento/Backend/etc/adminhtml/di.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,9 @@
122122
</argument>
123123
</arguments>
124124
</type>
125+
<type name="Magento\Framework\App\Response\XFrameOptPlugin">
126+
<arguments>
127+
<argument name="xFrameOpt" xsi:type="const">Magento\Framework\App\Response\XFrameOptPlugin::BACKEND_X_FRAME_OPT</argument>
128+
</arguments>
129+
</type>
125130
</config>

app/code/Magento/Store/etc/di.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
<preference for="Magento\Framework\App\Request\PathInfoProcessorInterface" type="Magento\Store\App\Request\PathInfoProcessor" />
1010
<preference for="Magento\Store\Model\StoreManagerInterface" type="Magento\Store\Model\StoreManager" />
1111
<preference for="Magento\Framework\App\Response\RedirectInterface" type="Magento\Store\App\Response\Redirect" />
12+
<type name="Magento\Framework\App\Response\Http">
13+
<plugin name="xFrameOptionsHeader" type="Magento\Framework\App\Response\XFrameOptPlugin"/>
14+
</type>
15+
<type name="Magento\Framework\App\Response\XFrameOptPlugin">
16+
<arguments>
17+
<argument name="xFrameOpt" xsi:type="init_parameter">Magento\Framework\App\Response\XFrameOptPlugin::DEPLOYMENT_CONFIG_X_FRAME_OPT</argument>
18+
</arguments>
19+
</type>
1220
<type name="Magento\Framework\App\Config\ScopePool">
1321
<arguments>
1422
<argument name="readerPool" xsi:type="object">Magento\Store\Model\Config\Reader\ReaderPool\Proxy</argument>

lib/internal/Magento/Framework/App/Response/Http.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class Http extends \Magento\Framework\HTTP\PhpEnvironment\Response
2121
/** Format for expiration timestamp headers */
2222
const EXPIRATION_TIMESTAMP_FORMAT = 'D, d M Y H:i:s T';
2323

24+
/** X-FRAME-OPTIONS Header name */
25+
const HEADER_X_FRAME_OPT = 'X-Frame-Options';
26+
2427
/** @var \Magento\Framework\Stdlib\CookieManagerInterface */
2528
protected $cookieManager;
2629

@@ -51,6 +54,17 @@ public function __construct(
5154
$this->dateTime = $dateTime;
5255
}
5356

57+
/**
58+
* Sends the X-FRAME-OPTIONS header to protect against click-jacking
59+
*
60+
* @param string $value
61+
* @return void
62+
*/
63+
public function setXFrameOptions($value)
64+
{
65+
$this->setHeader(self::HEADER_X_FRAME_OPT, $value);
66+
}
67+
5468
/**
5569
* Send Vary cookie
5670
*
@@ -109,6 +123,7 @@ public function setPrivateHeaders($ttl)
109123
* Set headers for no-cache responses
110124
*
111125
* @return void
126+
* @codeCoverageIgnore
112127
*/
113128
public function setNoCacheHeaders()
114129
{
@@ -122,6 +137,7 @@ public function setNoCacheHeaders()
122137
*
123138
* @param string $content String in JSON format
124139
* @return \Magento\Framework\App\Response\Http
140+
* @codeCoverageIgnore
125141
*/
126142
public function representJson($content)
127143
{
@@ -131,6 +147,7 @@ public function representJson($content)
131147

132148
/**
133149
* @return string[]
150+
* @codeCoverageIgnore
134151
*/
135152
public function __sleep()
136153
{
@@ -141,6 +158,7 @@ public function __sleep()
141158
* Need to reconstruct dependencies when being de-serialized.
142159
*
143160
* @return void
161+
* @codeCoverageIgnore
144162
*/
145163
public function __wakeup()
146164
{
@@ -154,6 +172,7 @@ public function __wakeup()
154172
*
155173
* @param string $time
156174
* @return string
175+
* @codeCoverageIgnore
157176
*/
158177
protected function getExpirationHeader($time)
159178
{
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/***
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\App\Response;
8+
9+
/**
10+
* Adds an X-FRAME-OPTIONS header to HTTP responses to safeguard against click-jacking.
11+
*/
12+
class XFrameOptPlugin
13+
{
14+
/** Deployment config key for frontend x-frame-options header value */
15+
const DEPLOYMENT_CONFIG_X_FRAME_OPT = 'x-frame-options';
16+
17+
/** Always send SAMEORIGIN in backend x-frame-options header */
18+
const BACKEND_X_FRAME_OPT = 'SAMEORIGIN';
19+
20+
/**
21+
*The header value
22+
* @var string
23+
*/
24+
private $xFrameOpt;
25+
26+
/**
27+
* @param string $xFrameOpt
28+
*/
29+
public function __construct($xFrameOpt)
30+
{
31+
$this->xFrameOpt = $xFrameOpt;
32+
}
33+
34+
/**
35+
* @param \Magento\Framework\App\Response\Http $subject
36+
* @return void
37+
* @codeCoverageIgnore
38+
*/
39+
public function beforeSendResponse(\Magento\Framework\App\Response\Http $subject)
40+
{
41+
$subject->setXFrameOptions($this->xFrameOpt);
42+
}
43+
}

lib/internal/Magento/Framework/App/Test/Unit/Response/HttpTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,4 +271,11 @@ public function testWakeUpWith()
271271
\Magento\Framework\App\ObjectManager::setInstance($objectManagerMock);
272272
$this->model->__wakeup();
273273
}
274+
275+
public function testSetXFrameOptions()
276+
{
277+
$value = 'DENY';
278+
$this->model->setXFrameOptions($value);
279+
$this->assertSame($value, $this->model->getHeader(Http::HEADER_X_FRAME_OPT)->getFieldValue());
280+
}
274281
}

lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class ConfigOptionsListConstants
2222
const CONFIG_PATH_DB_CONNECTION_DEFAULT = 'db/connection/default';
2323
const CONFIG_PATH_DB_CONNECTIONS = 'db/connection';
2424
const CONFIG_PATH_DB_PREFIX = 'db/table_prefix';
25+
const CONFIG_PATH_X_FRAME_OPT = 'x-frame-options';
2526
/**#@-*/
2627

2728
/**#@+
@@ -67,7 +68,7 @@ class ConfigOptionsListConstants
6768
const KEY_INIT_STATEMENTS = 'initStatements';
6869
const KEY_ACTIVE = 'active';
6970
/**#@-*/
70-
71+
7172
/**
7273
* Db config key
7374
*/

setup/src/Magento/Setup/Model/ConfigGenerator.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,18 @@ public function createResourceConfig()
210210

211211
return $configData;
212212
}
213+
214+
/**
215+
* Creates x-frame-options header config data
216+
*
217+
* @return ConfigData
218+
*/
219+
public function createXFrameConfig()
220+
{
221+
$configData = new ConfigData(ConfigFilePool::APP_ENV);
222+
if ($this->deploymentConfig->get(ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT) === null) {
223+
$configData->set(ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT, 'SAMEORIGIN');
224+
}
225+
return $configData;
226+
}
213227
}

setup/src/Magento/Setup/Model/ConfigOptionsList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public function createConfig(array $data, DeploymentConfig $deploymentConfig)
158158
}
159159
$configData[] = $this->configGenerator->createDbConfig($data);
160160
$configData[] = $this->configGenerator->createResourceConfig();
161+
$configData[] = $this->configGenerator->createXFrameConfig();
161162
return $configData;
162163
}
163164

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/***
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Setup\Test\Unit\Model;
8+
9+
10+
use Magento\Framework\Config\ConfigOptionsListConstants;
11+
12+
class ConfigGeneratorTest extends \PHPUnit_Framework_TestCase
13+
{
14+
/** @var \Magento\Framework\App\DeploymentConfig | \PHPUnit_Framework_MockObject_MockObject */
15+
private $deploymentConfigMock;
16+
/** @var \Magento\Setup\Model\ConfigGenerator | \PHPUnit_Framework_MockObject_MockObject */
17+
private $model;
18+
19+
public function setUp()
20+
{
21+
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
22+
23+
$this->deploymentConfigMock = $this->getMockBuilder('Magento\Framework\App\DeploymentConfig')
24+
->disableOriginalConstructor()
25+
->getMock();
26+
$this->model = $objectManager->getObject(
27+
'Magento\Setup\Model\ConfigGenerator',
28+
['deploymentConfig' => $this->deploymentConfigMock]
29+
);
30+
}
31+
32+
public function testCreateXFrameConfig()
33+
{
34+
$this->deploymentConfigMock->expects($this->atLeastOnce())
35+
->method('get')
36+
->with(ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT)
37+
->willReturn(null);
38+
$configData = $this->model->createXFrameConfig();
39+
$this->assertSame('SAMEORIGIN', $configData->getData()[ConfigOptionsListConstants::CONFIG_PATH_X_FRAME_OPT]);
40+
}
41+
}

0 commit comments

Comments
 (0)