diff --git a/src/CsrfParametersInjectionInterface b/src/CsrfParametersInjectionInterface new file mode 100644 index 0000000..2ec0b07 --- /dev/null +++ b/src/CsrfParametersInjectionInterface @@ -0,0 +1,38 @@ +|string> + */ +interface CsrfParametersInjectionInterface +{ + /** + * Returns array of csrf parameters,then merge to common parameters and metaTag parameters. + * + * + * For example: + * + * ```php + * [ + * [ '_csrf' => $csrf ], + * [ + * 'csrf' => [ + * 'name' => 'csrf' , + * 'content' => $tokenValue + * ], + * ], + * ... + * ] + * ``` + * + * @return array + * + * @psalm-return csrfParameters + */ + public function getCsrfParameters(): array; +} diff --git a/src/CsrfViewInjection.php b/src/CsrfViewInjection.php index 8b03a56..cb39471 100644 --- a/src/CsrfViewInjection.php +++ b/src/CsrfViewInjection.php @@ -5,14 +5,16 @@ namespace Yiisoft\Yii\View\Renderer; use LogicException; -use Yiisoft\Csrf\CsrfMiddleware; use Yiisoft\Csrf\CsrfTokenInterface; +use Yiisoft\Csrf\CsrfTrait; /** * `CsrfViewInjection` injects the necessary data into the view to protect against a CSRF attack. */ -final class CsrfViewInjection implements CommonParametersInjectionInterface, MetaTagsInjectionInterface +final class CsrfViewInjection implements CsrfParametersInjectionInterface { + use CsrfTrait; + public const DEFAULT_META_ATTRIBUTE_NAME = 'csrf'; public const DEFAULT_PARAMETER_NAME = 'csrf'; public const META_TAG_KEY = 'csrf'; @@ -20,57 +22,34 @@ final class CsrfViewInjection implements CommonParametersInjectionInterface, Met private string $metaAttributeName = self::DEFAULT_META_ATTRIBUTE_NAME; private string $parameterName = self::DEFAULT_PARAMETER_NAME; - public function __construct(private CsrfTokenInterface $token, private CsrfMiddleware $middleware) - { - } - - /** - * Returns a new instance with the specified parameter name. - * - * @param string $parameterName The parameter name. - */ - public function withParameterName(string $parameterName): self + public function __construct(private CsrfTokenInterface $token) { - $new = clone $this; - $new->parameterName = $parameterName; - return $new; } - /** - * Returns a new instance with the specified meta attribute name. - * - * @param string $metaAttributeName The meta attribute name. - */ - public function withMetaAttributeName(string $metaAttributeName): self - { - $new = clone $this; - $new->metaAttributeName = $metaAttributeName; - return $new; - } /** * @throws LogicException when CSRF token is not defined */ - public function getCommonParameters(): array + public function getCsrfParameters(): array { + $tokenValue = $this->token->getValue(); $csrf = new Csrf( - $this->token->getValue(), - $this->middleware->getParameterName(), - $this->middleware->getHeaderName(), + $tokenValue, + $this->getFormParameterName(), + $this->getHeaderName(), ); - return [$this->parameterName => $csrf]; - } - - /** - * @throws LogicException when CSRF token is not defined - */ - public function getMetaTags(): array - { return [ - self::META_TAG_KEY => [ - 'name' => $this->metaAttributeName, - 'content' => $this->token->getValue(), + [ + $this->parameterName => $csrf + ], + [ + self::META_TAG_KEY => [ + 'name' => $this->metaAttributeName, + 'content' => $tokenValue + ], ], ]; } + + } diff --git a/src/ViewRenderer.php b/src/ViewRenderer.php index 2845f8d..1ec5a73 100644 --- a/src/ViewRenderer.php +++ b/src/ViewRenderer.php @@ -111,12 +111,13 @@ public function getViewPath(): string */ public function render(string $view, array $parameters = []): DataResponse { - $commonParameters = $this->getCommonParameters(); + $csrfParameters = $this->getCsrfParameters(); + $commonParameters = array_merge($this->getCommonParameters(), $csrfParameters[0]); $layoutParameters = $this->getLayoutParameters(); - $metaTags = $this->getMetaTags(); + $metaTags = array_merge($this->getMetaTags(), $csrfParameters[1]); $linkTags = $this->getLinkTags(); - return $this->responseFactory->createResponse(fn (): string => $this->renderProxy( + return $this->responseFactory->createResponse(fn(): string => $this->renderProxy( $view, $parameters, $commonParameters, @@ -336,7 +337,7 @@ private function renderProxy( $layoutParameters = array_filter( $injectLayoutParameters, /** @psalm-suppress MissingClosureParamType */ - static fn ($_value, string $key): bool => !$currentView->hasParameter($key), + static fn($_value, string $key): bool => !$currentView->hasParameter($key), ARRAY_FILTER_USE_BOTH, ); @@ -345,6 +346,24 @@ private function renderProxy( ->render($layout, ['content' => $content]); } + + /** + * Gets csrf injection parameters merged with parameters specified during rendering. + * + * + * @return array The csrf injection parameters ot merged to common parameters and metaTag parameters. + * + * @psalm-return array + */ + private function getCsrfParameters(): array + { + $parameters = []; + foreach ($this->getInjections($this->layout, CsrfParametersInjectionInterface::class) as $injection) { + $parameters[] = $injection->getCsrfParameters(); + } + return array_merge(...$parameters); + } + /** * Gets injection common parameters merged with parameters specified during rendering. *