浏览代码

Add safe redirect functionality.

mscherer 7 年之前
父节点
当前提交
ed47336c26

+ 23 - 0
src/Controller/Component/CommonComponent.php

@@ -38,6 +38,29 @@ class CommonComponent extends Component {
 	}
 
 	/**
+	 * Returns internal redirect only, otherwise falls back to default.
+	 *
+	 * Lookup order:
+	 * - POST data
+	 * - query string
+	 * - provided default
+	 *
+	 * @param string|array $default
+	 * @param string|array|null $data
+	 * @param string $key
+	 *
+	 * @return string|array
+	 */
+	public function getSafeRedirectUrl($default, $data = null, $key = 'redirect') {
+		$redirectUrl = $data ?: ($this->Controller->getRequest()->getData($key) ?: $this->Controller->getRequest()->getQuery($key));
+		if ($redirectUrl && (substr($redirectUrl, 0, 1) !== '/' || substr($redirectUrl, 0, 2) === '//')) {
+			$redirectUrl = null;
+		}
+
+		return $redirectUrl ?: $default;
+	}
+
+	/**
 	 * List all direct actions of a controller
 	 *
 	 * @return array Actions

+ 20 - 0
tests/TestCase/Controller/Component/CommonComponentTest.php

@@ -200,4 +200,24 @@ class CommonComponentTest extends TestCase {
 		$this->assertSame(302, $this->Controller->response->statusCode());
 	}
 
+	/**
+	 * @return void
+	 */
+	public function testGetSafeRedirectUrl() {
+		$result = $this->Controller->Common->getSafeRedirectUrl(['action' => 'default']);
+		$this->assertSame(['action' => 'default'], $result);
+
+		$this->request = $this->request->withQueryParams(['redirect' => '/foo/bar']);
+		$this->Controller->setRequest($this->request);
+
+		$result = $this->Controller->Common->getSafeRedirectUrl(['action' => 'default']);
+		$this->assertSame('/foo/bar', $result);
+
+		$this->request = $this->request->withQueryParams(['redirect' => 'https://dangerous.url/foo/bar']);
+		$this->Controller->setRequest($this->request);
+
+		$result = $this->Controller->Common->getSafeRedirectUrl(['action' => 'default']);
+		$this->assertSame(['action' => 'default'], $result);
+	}
+
 }