Pull to refresh

PHP5. «Безопасные шаблоны»

Reading time4 min
Views497
Исторически сложилось, что я не пользуюсь внешними шаблонизаторами типа Smarty или другими. Я использую основной «активный» шаблон, т.е. просто PHP файл в котором вызываются и вставляются данные для контент зон в виде простого HTML (как он формируется в данном случае не имеет значения). В предыдущей версии CMS, которая была не «коробочной» и в которой фактически не было разделения прав пользователей, данный аспект особо не напрягал — доступ к шаблону был либо «прямой» (фтп и прочее) либо через администраторский интерфейс для администратора. Но соответственно человек имеющий доступ к админке мог напихать вовнутрь этого файла любой php код. В новой версии CMS это неприемлемо, т.к. это фактически обход разграничения прав. Поэтому было решено отказаться от таких «небезопасных» шаблонов.

В поисках наиболее простого и изящного выхода, с использованием по минимуму «внешних» решений, я вспомнил об одной замечательной особенности встроенного в PHP XSLT процессора (XSLTProcessor). А именно — использование в трансформациях функций PHP, при этом можно ограничить список этих фукнций. А этот как раз то, что необходимо.

Перейдем к примерам.

Стандартный «активный» шаблон выглядел следующим образом:

<?php<br>$main_ctx = CMSContentObj::getInstance()->getData("main_ctx");<br>$title = CMSContentObj::getInstance()->getTitle();<br>// тут еще много вызовов<br>?><br><html><br><head><br><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><br><title><?=$title;?> - mysite.ru</title><br><link href="/_css/main.css" rel="stylesheet" type="text/css"><br><script type="text/javascript" src="/_js/jquery.js"></script><br></head><br><body><br>…<br><?=$main_ctx;?><br>…<br></body><br></html><br><br>* This source code was highlighted with Source Code Highlighter.


Т.е. просто с контента вытаскиваются именованные HTML данные и вставляются в HTML код.

В случае с XSL шаблон выглядит след образом:

<?xml version="1.0" encoding="utf-8"?><br><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl"><br>  <xsl:output encoding="utf-8" indent="yes" method="html"/><br>  <xsl:template match="/page"><br>    <!--<br>     Variables<br>    --><br>    <xsl:variable name="title" select="php:function('CMSStaticContent::getTitle')"/><br>    <xsl:variable name="main_ctx" select="php:function('CMSStaticContent::getData','main_ctx')"/><br>    <!--<br>    / Variables<br>    --><br>    <html><br>      <head><br>        <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><br>        <title><xsl:value-of disable-output-escaping="yes" select="$title"/> - mysite.ru</title><br>        <link href="/_css/main.css" rel="stylesheet" type="text/css"/><br>        <script type="text/javascript" src="/_js/jquery.js"/><br>      </head><br>      <body><br>        …<br>        <xsl:value-of disable-output-escaping="yes" select="$main_ctx"/><br>        …<br>      </body><br>    </html><br>  </xsl:template><br></xsl:stylesheet><br><br>* This source code was highlighted with Source Code Highlighter.


Не правда ли, похоже?

LS: У меня почему то не получилось использовать конструкции вида CMSContentObj::getInstance()->getTitle(), поэтому пришлось «на коленке» создать промежуточный класс CMSStaticContent:

class CMSStaticContent {<br>  public static function __callStatic($name, $arguments) {<br>    $cms = CMSContentObj::getInstance();<br>    if (method_exists($cms, $name)) {<br>      return call_user_func_array(array($cms, $name), $arguments);<br>    } else {<br>      throw new Exception();<br>    }<br>  }<br>}<br><br>* This source code was highlighted with Source Code Highlighter.


Ну теперь просто остается создать пустой XML, зарегистрировать функции и сделать преобразование, например так:

$doc = new DOMDocument();<br>$doc->loadXML('<page/>');<br>$xsl = new DOMDocument();<br>$xsl->load($xsl_template);<br>$proc = new XSLTProcessor();<br>$proc->registerPHPFunctions(array('CMSStaticContent::getData’, ‘CMSStaticContent::getTitle’));<br>$proc->importStyleSheet($xsl);<br>echo $proc->transformToXML($doc);<br><br>* This source code was highlighted with Source Code Highlighter.


Ну вот, собственно говоря и все. Мы ограничили PHP функции, которые могут выполняться при преобразовании, и через такой шаблон невозможно поиметь доступ к системе.

PS: И никаких внешних шаблонизаторов.
Tags:
Hubs:
Total votes 18: ↑7 and ↓11-4
Comments5

Articles