问题描述
如果变量包含以下内容:
$sTraddr = "1 elm street<br>Unit 4<br><i>City UnkNown</i>Alabama";
并且我想将该变量包含在 Blade 模板中,我可以这样做:
<td>{{ $sTraddr }}</td>
然而,the documentation 说
默认情况下,Blade {{ }}
语句会通过 PHP 的 htmlspecialchars
函数自动发送,以防止 XSS 攻击。如果您不希望您的数据被转义,您可以使用以下语法:
Hello,{!! $name !!}.
在刀片文件中使用 {!! $variable !!}
语法似乎非常危险。还是在这种情况下?
不转义来自数据库的数据是否风险太大?
解决方法
在评论中,我们确定此 HTML 实际上是由您在您的控制器方法中生成的。所以真正的问题是,你为什么要为了颠覆 MVC 范式而大费周章?
假设您有一个 User
模型,其属性为 address_1
、address_2
、address_3
、city
、state
和 {{1} },这就是你需要做的。
zip_code
您提供的其余代码正在执行数据验证,绝对不应在数据生命周期的这个阶段进行。您的数据应在进入应用程序时进行验证,无论是用户输入、CSV 导入还是其他任何方式。您不必将城市名称大写,确定您的地址是否超过 3 个字符,或者在显示时想知道是否有州的缩写或全名。
,用户提供的任何数据,即使存储在中间的数据库中,默认情况下也应被视为不安全。在这种特殊情况下,您面临着存储型 XSS 的风险。
您应该确保您的数据可能是
- 转义(
htmlspecialchars
、strip_tags
等)和 - 已验证(您能否强制执行模式、字符限制(仅限 A-Z 或数字)或长度限制?)
好的,就是这样。在 Blade 组件或模板中使用的 {{ }} 将始终将标签呈现为 html 实体。所以关键是,正如上面的 miken32 所说,在返回字符串之前简单地在字符串上使用 strip_tags,然后使用 {!! !!} 将
标记呈现为实际的中断标记而不是 html 实体。
谢谢 miken 和 speckulatius。
好的,我确信 strip_tags 不是一个好主意。所以这里又是一个问题,也许是一个答案。答案之一就是编辑 Blade 模板,这样您就可以将
标签直接放在模板中,而不是冒着将它放在数据库中的风险。但我认为它仍然可以在后端完成。这是我用来在数据表中呈现某人的地址的函数。
public function getFullAddressFhAttribute(){
$a1 = (!is_null($this->address_1) && strlen(trim($this->address_1))>3) ? ucWordsSpace(trim($this->address_1),'addr') : '';
$a2 = (!is_null($this->address_2) && strlen(trim($this->address_2))>3) ? ucWordsSpace(trim($this->address_2),'addr') : '';
$a3 = (!is_null($this->address_3) && strlen(trim($this->address_3))>3) ? ucWordsSpace(trim($this->address_3),'addr') : '';
$c = (!is_null($this->city) && strlen(trim($this->city))>2) ? Str::title(trim($this->city)) : '';
$s = (!is_null($this->state) && strlen(trim($this->state))>1) ? trim($this->state) : '';
$s = (strlen($s)==2) ? strtoupper($s) : Str::title($s);
$z = (!is_null($this->zip_code) && strlen(trim($this->zip_code))>4) ? formatzip($this->zip_code) : '' ;
$address = (strlen($a1)>3) ? $a1 : '';
$address .= (strlen($address)>3 && strlen($a2)>3) ? "<br>$a2" : '';
$address .= (strlen($address)>3 && strlen($a3)>3) ? "<br>$a3" : '';
$address = (strlen($address)>3) ? $address . "<br>" : "<i>Street Addr Unknown</i><br>";
if(strlen($c.$s)==0)
$address .= "<i>City,State Unknown</i>";
else{
$address .= (strlen($c)>2) ? "$c," : "?,";
$address .= (strlen($s)>1) ? " $s" : " ?";
}
$address .= (strlen($z)>4) ? " $z" : '';
$safeElements = ["<br>","<b>","<i>"];
return strip_tags($address,$safeElements);
}
我认为上面的函数如果重写为前 7 个变量的 strip_tags 会更安全,就像这样:
public function getFullAddressFhAttribute(){
$a1 = (!is_null($this->address_1) && strlen(trim($this->address_1))>3) ? ucWordsSpace(trim($this->address_1),'addr') : '';
$c = (!is_null($this->city) && strlen(trim($this->city))>2) ? Str::title(trim($this->city)) : '';
$s = (!is_null($this->state) && strlen(trim($this->state))>1) ? trim($this->state) : '';
$s = (strlen($s)==2) ? strtoupper($s) : Str::title($s);
$z = (!is_null($this->zip_code) && strlen(trim($this->zip_code))>4) ? formatzip($this->zip_code) : '' ;
$a1 = strip_tags($a1);
$a2 = strip_tags($a2);
$a3 = strip_tags($a3);
$c = strip_tags($c);
$s = strip_tags($s);
$z = strip_tags($z);
$address = (strlen($a1)>3) ? $a1 : '';
$address .= (strlen($address)>3 && strlen($a2)>3) ? "<br>$a2" : '';
$address .= (strlen($address)>3 && strlen($a3)>3) ? "<br>$a3" : '';
$address = (strlen($address)>3) ? $address . "<br>" : "<i>Street Addr Unknown</i><br>";
if(strlen($c.$s)==0)
$address .= "<i>City,$safeElements);
}
因此,在将安全标签放到后端之前,先去掉所有标签。