Yii2フレームの几二セキュリティの坑
摘要:Yii2是一項优秀的通用Web后端フレーム、结构简单优雅、实用功能富、扩展性强、性能搞是他一番突き出たそれらの優れた場所は、使用中に常に容易に発見できるため、特に説明する必要はありません。
目次
ゴシップの話をしましょう
最後にブログを書いてから 3 か月が経ちました。書き始める前に、私はいつも深い罪悪感を感じます。長い間悩んだ末、ついに行動を起こしました。
記念すべきことが 1 つあります。最近、毎朝 8:30 に起きて運動するようになりました。非常に役立つビデオが 2 つあり、所要時間はわずか 8 分です。これをフォローするだけで、爆発的に死ぬことはなく、幸せになることを保証します。 (8 分間の腹筋エクササイズ レベル 2 - ダウンロード、8 分間の胸筋エクササイズ レベル 2 - ダウンロード)
反省すべきことの 1 つは、最近「ショーペンハウアーの美学に関するエッセイ」を読んだことで、読書に対する私の態度が変わりました。読書こそが進歩の源だと思っていたのですが、この本で大きく顔を殴られました。さあ、次の段落を共有しましょう:
私たちが目にする外部環境は、特定の意見を私たちの心に押し付ける読み物のようなものではなく、私たちに材料と機会を提供するだけです。私たちの精神的能力に見合ったもの、そして現在の感情と一致するものを考えること。したがって、重い物体をバネに押し続けるとバネの弾力性が失われるのと同じように、本を読みすぎると精神の弾力性が失われます。自分の考えを持たないようにする最も安全な方法は、すべてを読むことです。すぐに本を手に取ってください。
考えることは進歩の源です!
さて、ナンセンスな話はこれくらいにして、本題に入りましょう。
ActiveRecord は不可解に書かれていましたか?
準備知識
ActiveRecord
の基本的な使い方。分からない場合はここを参照してください。 ActiveRecord
的基本用法。如果不理解,可参考这里。代码现场
<span>/**</span><span> * @property integer $id</span><span> * @property string $name</span><span> * @property string $detail</span><span> * @property double $price</span><span> * @property integer $area</span><span> **/</span><span>class OcRoom extends ActivieRecord</span><span>{</span><span> ...</span><span>}</span><span>$room = OcRoom::find() //先取出一个对象。</span><span> ->select(['id']) //只取出'id'列</span><span> ->where(['id'=>20])</span><span> ->one();</span><span>$room->save(); //保存,会发现此行的其它字段都被写成默认值了。</span>
总结问题
这个例子的问题在于:
$room
,但是只取出了id
字段,而其他字段自然就是默认值。$room->save()
的时候,那些是默认值的字段也被保存到数据库里去了。what!?解决方法
然而,我们有什么解决办法呢?提供几种思路:
ActiveRecord
的保存。ActiveRecord
, 使得,当此对象由find()
新建,且字段没有完全取出,调用save()
方法,抛出异常。ActiveRecord
,使得,当此对象由find()
新建,且字段没有完全取出,调用save()
方法时,只保存取出过的字段,其他字段被忽略。你的Transaction生效了吗?
代码现场
<span>/**</span><span> * @property integer $id</span><span> * @property string $name</span><span> **/</span><span>class OcRoom extends ActiveRecord</span><span>{</span><span> public function rules()</span><span> {</span><span> return [['name','string','min'=>2,'max'=>10]];</span><span> }</span><span> ...</span><span>}</span><span>class OcHouse extends ActiveRecord</span><span>{</span><span> public function rules()</span><span> {</span><span> return [['name','string','max'=>10]];</span><span> }</span><span> ...</span><span>}</span><span>$a = new OcRoom();</span><span>$a->name = ''; //name为空字符串,不满足rules()条件。</span><span>$b = new OcHouse();</span><span>$b->name = '我的房间'; //name合法,可以保存。</span><span>$transaction = Yii::$app->db->beginTransaction();</span><span>try{</span><span> $a->save(); //name字段不合法,无法验证通过,在validate()阶段已经返回false,不会进行数据库存储的步骤,所以也不会抛出异常。</span><span> $b->save(); //name字段合法,可以正常保存。</span><span> $transaction->commit(); //提交后,发现$a保存失败,而$b保存成功。</span><span>}</span><span>catch (Exception $e) </span><span>{</span><span> Yii::error($e->getTraceAsString(),__METHOD__);</span><span> $transaction->rollBack();</span><span>}</span>
问题总结
这段代码的问题在于:
$transaction
的存在意义是保证整段数据库存储代码要么全成功,要么全失败。transaction
并没有达到我们想要的效果:$a
因为validate()
都没过,所以$transation->commit()
的时候并不会报错。解决方法
在$transation
块内,所有的save()
都要判断下返回值,如果为false
,则直接抛出异常。
'Y-m-d'不被识别?
代码现场
<span>OcRenterBill extends ActiveRecord</span><span>{</span><span> public function rules()</span><span> {</span><span> return [</span><span> ['start_time','date','format'=>'Y-m-d'],</span><span> ];</span><span> }</span><span>}</span><span>$a = new OcRenterBill();</span><span>$a = '2015-09-12';</span><span>$a->save(); //会报错,说格式不对。</span>
问题总结
如果一开始,Yii框架就报错,这个还不算坑。坑的是我在Mac上开发时,这个可以完全正常的工作,而发布到线上环境(Ubuntu)后,就弹出“属性start_time格式无效”的错误。而参考官方文档,发现这种格式是允许的官方文档。
啊啊啊。各种试错,最后发现如果改成php:Y-m-d