今天我說一下怎麼在框架中over掉這些安全問題。 php
首先是SQL注入,這個若是你使用的是PDO,我以爲應該沒什麼問題,若是你使用的仍是mysql_*等API,那麼你能夠在框架中實現bindParameter或者在插入數據庫以前進行字符串轉義。 mysql
前兩天把上一篇文章寫完以後,Vian在後面留言說到過SQL注入的一個解決方案,就是在在插入DB以前進行'''.addslashes($id).''',它的意思就是首先進行addslashes操做,以後再強制單引號包裹,這樣它就是一個徹徹底底的字符串了,因此就注入不了,我以爲這個方法不錯,贊一個!! 程序員
因爲SQL注入須要聯繫到模型,XSS須要聯繫到視圖,這兩塊兒我都沒有開始講,因此我再後面再講怎麼在框架中解決,固然,若是我寫到後面忘記了,你也能夠提醒我一下。 sql
上一次我講CSRF的時候,並無給出一個解決方案,今天我就給出這個解決方案。實際上解決的方法很簡單,就是給它產生一個隨機數,而後後端斷定傳遞過來的數和正確的數是否吻合, 若是不吻合,就不執行相應的代碼了,這個隨機數咱們稱爲token。 數據庫
爲了簡單,咱們就將產生token和獲得token的函數都寫在控制器中,即Controller.php。 後端
首先是生成隨機數,最簡單的方式是使用mt_rand()直接產生一個整數,但在這兒我使用以前我在initphp這個框架中看到的解決csrf的方法,在這兒,也謝謝initphp做者的思路: 安全
initphp的代碼是: cookie
private function set_token() { if (!$_COOKIE['init_token']) { $str = substr(md5(time(). $this->get_useragent()), 5, 8); setcookie("init_token", $str, NULL, '/'); $_COOKIE['init_token'] = $str; } }爲了簡單,我這兒就不使用userAgent了,initphp是將當前時間戳和userAgent拼接成字符串以後再md5加密,取出第5到8位,我這邊的思路是將當前時間戳進行md5加密,而後從第0位開始取,取得的字符串長度是隨機產生的:
$token = substr(md5(time()),0,mt_rand(10,15));爲了防止隨機數太大或過小,我設置mt_rand的取值範圍爲10到15,也就是說產生的token的位數爲10到15位。
生成token以後其餘的事情就好辦了,固然,首先,也是設置token,咱們沒有必要每次用戶請求的時候都產生一個隨機數,因此咱們將它存放在COOKIE中,框架載入的時候會斷定是否有token,若是沒有則動態生成一個,固然,生成的token會在一段時間以後過時失效,我這兒設置的時間爲7天。 框架
private function _setToken() { if(empty($_COOKIE['_csrfToken'])) { $token = substr(md5(time()),0,mt_rand(10,15)); $this->_token = $token; setcookie('_csrfToken',$token,time() + 3600 * 24 * 7); } else { $this->_token = $_COOKIE['_csrfToken']; } }
因爲生成token的過程是框架自動完成的,因此沒有必要讓用戶看到此過程,因此將這個函數設爲私有,而後在Controller類的構造函數中調用便可。 jsp
剛纔是生成token,那麼怎麼獲得token呢,實際上獲得token的方法就很是簡單了,就是一個簡單的getter:
protected function _getToken() { return $this->_token; }如今我再演示一下在用戶編寫的控制器的斷定過程:
假設用戶請求的URL是:http://localhost/index.php?c=Index&a=test&token=rwerdfdsfsdfs
那麼這個控制器的類的代碼以下:
<?php class IndexController extends Controller { public function test() { $token = empty($_GET['token']) ? '' : $_GET['token']; if($token === $this->_getToken()) { //斷定爲正常 } else { $this->_redirect(array( //跳轉到某一個控制器的某一個Action )); } } }可能有人會問URl上面的token值是怎麼設置而後傳遞過來的呢?
咱們能夠想一下,假設上一個頁面是Index控制器的test2這個Action,那麼咱們能夠在test2這個Action中首先使用$this->_getToken獲得token值,而後在將數據傳遞到視圖,視圖中使用了以後,用戶點擊這個連接就能夠將這個token值傳遞過來了。
我如今提一個問題,假設用戶訪問A頁面的時候獲得token,這個token還有兩秒就過時了,這個用戶三秒以後點擊這個含有token的連接到達B頁面,B頁面因爲COOKIE中的token已經失效,因此從新產生一個token,而後再和傳遞的這個token比較,天然不匹配,而後就跳轉了,這還不是有問題的呢,那麼怎麼解決呢?
因爲還有一點時間,因此我提一下上傳文件漏洞吧,用戶上傳一個好比test.php頁面,若是用戶沒有作文件類型的斷定,用戶上傳這個php文件以後,按照連接訪問這個頁面,有可能這個頁面中有一些破壞性的代碼,整個網站就危險了。
可能你已經在程序中斷定了,只容許後綴爲jpg,png,gif這三種類型,那麼我能夠將這個jsp頁面後綴改爲如jpg,上傳成功以後,若是網站存在某種漏洞可以讓它修改文件後綴,那麼你的網站又危險了!!
還假設你的網站不容許修改文件後綴名,可是它在上傳的圖片後面加上一段JS腳本或者在上傳的文件名上面寫一些腳本,這些均可能很危險!!
因此,作好一個WEB應用不是想象中那麼容易的,剛纔說的是安全這一起的內容,實際上當訪問量大了以後,以前你以爲徹底不是問題的問題可能就變成了一個大的問題,除了這兩個,還有其餘N個問題,因此,保持低調,繼續學習,繼續提升。。。。
上面一段話僅以自勉,其餘人能夠忽略。
大四了,還有一個月就要離開天貓回學校作畢設了,我很想在畢業以前給個人網站作一個大幅度的修改,可是我如今不知道到底要作什麼,不過確定這個網站是針對程序員的,但願你們提一點意見,個人我的網站http://www.qingyueit.com(比較挫,很久都沒有更新文章了,甚至連界面也是直接用了別人的主題)。
本次代碼點此下載