ホームページ  >  記事  >  バックエンド開発  >  [PHP] Yii2 フレームワークの落とし穴

[PHP] Yii2 フレームワークの落とし穴

WBOY
WBOYオリジナル
2016-07-30 13:31:041054ブラウズ

Yii2フレームの几二セキュリティの坑


摘要:Yii2是一項优秀的通用Web后端フレーム、结构简单优雅、实用功能富、扩展性强、性能搞是他一番突き出たそれらの優れた場所は、使用中に常に容易に発見できるため、特に説明する必要はありません。


  • ブログ: http://www.cnblogs.com/jhzhu
  • メール: jhzhuustc@gmail.com
  • 著者: Zhimingso
  • 時間: 2015-08-17

目次

  • Yii2 いくつかフレームワークの隠れた落とし穴
    • Directory
    • ゴシップの話をしましょう
    • ActiveRecord が不可解に書かれていましたか?
      • 知識を準備する
      • コードシーン
      • 問題の概要
      • 解決策
    • トランザクションは効果的ですか?
      • コードシーン
      • 問題の概要
      • 解決策
    • 「Y-m-d」が認識されませんか?
      • コードシーン
      • 問題の概要

ゴシップの話をしましょう

最後にブログを書いてから 3 か月が経ちました。書き始める前に、私はいつも深い罪悪感を感じます。長い間悩んだ末、ついに行動を起こしました。

記念すべきことが 1 つあります。最近、毎朝 8:30 に起きて運動するようになりました。非常に役立つビデオが 2 つあり、所要時間はわずか 8 分です。これをフォローするだけで、爆発的に死ぬことはなく、幸せになることを保証します。 (8 分間の腹筋エクササイズ レベル 2 - ダウンロード、8 分間の胸筋エクササイズ レベル 2 - ダウンロード)

反省すべきことの 1 つは、最近「ショーペンハウアーの美学に関するエッセイ」を読んだことで、読書に対する私の態度が変わりました。読書こそが進歩の源だと思っていたのですが、この本で大きく顔を殴られました。さあ、次の段落を共有しましょう:

私たちが目にする外部環境は、特定の意見を私たちの心に押し付ける読み物のようなものではなく、私たちに材料と機会を提供するだけです。私たちの精神的能力に見合ったもの、そして現在の感情と一致するものを考えること。したがって、重い物体をバネに押し続けるとバネの弾力性が失われるのと同じように、本を読みすぎると精神の弾力性が失われます。自分の考えを持たないようにする最も安全な方法は、すべてを読むことです。すぐに本を手に取ってください。

考えることは進歩の源です!

さて、ナンセンスな話はこれくらいにして、本題に入りましょう。

ActiveRecord は不可解に書かれていましたか?

準備知識

  1. 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>

总结问题

这个例子的问题在于:

  1. 我从数据库中取出了一行,也就是代码中的$room,但是只取出了id字段,而其他字段自然就是默认值。
  2. 当我$room->save()的时候,那些是默认值的字段也被保存到数据库里去了。what!?
  3. 也就是说,当你想节约资源,不取出所有字段的时候,一定要注意不能保存,否则,很多数据会被莫名修改为默认值。

解决方法

然而,我们有什么解决办法呢?提供几种思路:

  1. 自己时刻注意,避免未完全取出的ActiveRecord的保存。
  2. 修改或继承ActiveRecord, 使得,当此对象由find()新建,且字段没有完全取出,调用save()方法,抛出异常。
  3. 修改或继承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>

问题总结

这段代码的问题在于:

  1. 大家知道$transaction的存在意义是保证整段数据库存储代码要么全成功,要么全失败。
  2. 显然,在这个例子中,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

コードシーンrrreee
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:ELB側の啓蒙次の記事:ELB側の啓蒙