<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

    Linux架設(shè)時間服務(wù)器

     ntpdate 0.centos.pool.ntp.org
      在linux下,我們可以通過自帶的NTP(Network Time Protocol)協(xié)議通過網(wǎng)絡(luò)使自己的系統(tǒng)保持精確的時間。
      可用的公共時間服務(wù)器列表可以從下面的地址獲取:
      http://ntp.isc.org/bin/view/Servers/NTPPoolServers
      NTP是用來使系統(tǒng)和一個精確的時間源保持時間同步的協(xié)議。建議大家在自己管理的網(wǎng)絡(luò)中建立至少一臺時間服務(wù)器來同步本地時間,這樣可以使得在不同的系統(tǒng)上處理和收集日志和管理更加容易。
      介紹一下環(huán)境:179為本地時間服務(wù)器,其他服務(wù)器和179同步。179和網(wǎng)上時間服務(wù)器同步。
      一、配置179時間服務(wù)器
      1、首先查詢NTP軟件版本
      rpm -qa | grep ntp
      ntp-4.1.2-4.EL3.1
      如果沒有可以從linux安裝盤上查找,安裝此ntp包
      2、編輯配置文件
      vi /etc/ntp.conf
      首先定義服務(wù)器
      server pool.ntp.org
      restrict default nomodify notrap noquery
      restrict 192.168.0.0 mask 255.255.255.0 notrust nomodify notrap #從192.168.0.1-192.168.0.254的服務(wù)器都可以使用我們的NTP服務(wù)器來同步時間
      注釋掉以下一行
      #restrict default ignore
      3、啟動NTP服務(wù)器
      #chkconfig ntpd on
      #/etc/init.d/ntpd start
      #/etc/init.d/ntpd stop
      #/etc/init.d/ntpd restart
      默認(rèn)情況下,我們配置的NTP服務(wù)器不會去時間源那里同步時間,所以必須修改/etc/ntp/step-tickers文件,加入我們的時間源,這樣每次通過/etc/init.d/ntpd 來啟動服務(wù)的時候就會自動更新時間了
      檢查服務(wù)器同步狀態(tài):
      ntpq -p
      ntptrace 192.168.0.179
      如果輸出正確,則說明時間服務(wù)器成功。每次啟動服務(wù)器,會自動同步時間。

     二、配置LINUX客戶端
      在linux客戶端上執(zhí)行
      ntpdate ntp_server_ip
      就可以根據(jù)時間服務(wù)器統(tǒng)一局域網(wǎng)的時間了,將上面的命令放到cron里每天早上3點定期執(zhí)行
      crontab –e
      然后輸入
      0 3 * * * /usr/sbin/ntpdate 192.168.0.179
      下載安裝包:
      1、編譯安裝
      ntp server
      wget http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2.6.tar.gz tar zxvf ntp-4.2.6.tar.gz
      cd ntp-4.2.6
      ./configure --prefix=/usr/local/ntp --enable-all-clocks --enable-parse-clocks make && make install
      注:如以上下載地址無法訪問,請從NTP官方下載網(wǎng)頁(http://support.ntp.org/bin/view/Main/SoftwareDownloads)尋找下載地址。
      2、修改ntp.conf配置文件
      vi /etc/ntp.conf
      第一種配置:允許任何IP的客戶機都可以進行時間同步 將
      restrict default kod nomodify notrap nopeer noquery
      這行修改成:
      restrict default nomodify
      配置文件示例:/etc/ntp.conf
      第二種配置:只允許192.168.18.***網(wǎng)段的客戶機進行時間同步在
      restrict default nomodify notrap noquery(表示默認(rèn)拒絕所有IP的時間同步)
      之后增加一行:
      restrict 192.168.18.0 mask 255.255.255.0 nomodify
      配置文件示例:/etc/ntp.conf
      3、以守護進程啟動
      ntpd /usr/local/ntp/bin/ntpd -c /etc/ntp.conf -p /tmp/ntpd.pid
      4、ntpd啟動后,客戶機要等幾分鐘再與其進行時間同步,否則會提示“no server suitable for synchronization found”錯誤。
      三、配置時間同步客戶機
      vi /var/spool/cron/root
      增加一行,在每天的5點13分、9點13分、14點13分、19點13分與時間同步服務(wù)器進行同步
      13 5,9,14,19 * * * /usr/sbin/ntpdate 192.168.18.2
      備注:如果客戶機沒有ntpdate,可以下載ntpdate.tar.gz到/usr/sbin/目錄,然后解壓: wget http://blog.s135.com/attachment/200708/ntdate.tar.gz cd /usr/sbin/ tar zxvf ntpdate.tar.gz

    posted @ 2014-04-09 10:53 順其自然EVO 閱讀(245) | 評論 (0)編輯 收藏

    數(shù)據(jù)庫Sharding的基本思想和切分策略

     本文著重介紹sharding的基本思想和理論上的切分策略,關(guān)于更加細(xì)致的實施策略和參考事例請參考我的另一篇博文:數(shù)據(jù)庫分庫分表(sharding)系列(一) 拆分實施策略和示例演示
      一、基本思想
      Sharding的基本思想就要把一個數(shù)據(jù)庫切分成多個部分放到不同的數(shù)據(jù)庫(server)上,從而緩解單一數(shù)據(jù)庫的性能問題。不太嚴(yán)格的講,對于海量數(shù)據(jù)的數(shù)據(jù)庫,如果是因為表多而數(shù)據(jù)多,這時候適合使用垂直切分,即把關(guān)系緊密(比如同一模塊)的表切分出來放在一個server上。如果表并不多,但每張表的數(shù)據(jù)非常多,這時候適合水平切分,即把表的數(shù)據(jù)按某種規(guī)則(比如按ID散列)切分到多個數(shù)據(jù)庫(server)上。當(dāng)然,現(xiàn)實中更多是這兩種情況混雜在一起,這時候需要根據(jù)實際情況做出選擇,也可能會綜合使用垂直與水平切分,從而將原有數(shù)據(jù)庫切分成類似矩陣一樣可以無限擴充的數(shù)據(jù)庫(server)陣列。下面分別詳細(xì)地介紹一下垂直切分和水平切分.
      垂直切分的最大特點就是規(guī)則簡單,實施也更為方便,尤其適合各業(yè)務(wù)之間的耦合度非常低,相互影響很小,業(yè)務(wù)邏輯非常清晰的系統(tǒng)。在這種系統(tǒng)中,可以很容易做到將不同業(yè)務(wù)模塊所使用的表分拆到不同的數(shù)據(jù)庫中。根據(jù)不同的表來進行拆分,對應(yīng)用程序的影響也更小,拆分規(guī)則也會比較簡單清晰。(這也就是所謂的”share nothing”)。
      水平切分于垂直切分相比,相對來說稍微復(fù)雜一些。因為要將同一個表中的不同數(shù)據(jù)拆分到不同的數(shù)據(jù)庫中,對于應(yīng)用程序來說,拆分規(guī)則本身就較根據(jù)表名來拆分更為復(fù)雜,后期的數(shù)據(jù)維護也會更為復(fù)雜一些。
      讓我們從普遍的情況來考慮數(shù)據(jù)的切分:一方面,一個庫的所有表通常不可能由某一張表全部串聯(lián)起來,這句話暗含的意思是,水平切分幾乎都是針對一小搓一小搓(實際上就是垂直切分出來的塊)關(guān)系緊密的表進行的,而不可能是針對所有表進行的。另一方面,一些負(fù)載非常高的系統(tǒng),即使僅僅只是單個表都無法通過單臺數(shù)據(jù)庫主機來承擔(dān)其負(fù)載,這意味著單單是垂直切分也不能完全解決問明。因此多數(shù)系統(tǒng)會將垂直切分和水平切分聯(lián)合使用,先對系統(tǒng)做垂直切分,再針對每一小搓表的情況選擇性地做水平切分。從而將整個數(shù)據(jù)庫切分成一個分布式矩陣。
      二、切分策略
      如前面所提到的,切分是按先垂直切分再水平切分的步驟進行的。垂直切分的結(jié)果正好為水平切分做好了鋪墊。垂直切分的思路就是分析表間的聚合關(guān)系,把關(guān)系緊密的表放在一起。多數(shù)情況下可能是同一個模塊,或者是同一“聚集”。這里的“聚集”正是領(lǐng)域驅(qū)動設(shè)計里所說的聚集。在垂直切分出的表聚集內(nèi),找出“根元素”(這里的“根元素”就是領(lǐng)域驅(qū)動設(shè)計里的“聚合根”),按“根元素”進行水平切分,也就是從“根元素”開始,把所有和它直接與間接關(guān)聯(lián)的數(shù)據(jù)放入一個shard里。這樣出現(xiàn)跨shard關(guān)聯(lián)的可能性就非常的小。應(yīng)用程序就不必打斷既有的表間關(guān)聯(lián)。比如:對于社交網(wǎng)站,幾乎所有數(shù)據(jù)最終都會關(guān)聯(lián)到某個用戶上,基于用戶進行切分就是最好的選擇。再比如論壇系統(tǒng),用戶和論壇兩個模塊應(yīng)該在垂直切分時被分在了兩個shard里,對于論壇模塊來說,F(xiàn)orum顯然是聚合根,因此按Forum進行水平切分,把Forum里所有的帖子和回帖都隨Forum放在一個shard里是很自然的。
      對于共享數(shù)據(jù)數(shù)據(jù),如果是只讀的字典表,每個shard里維護一份應(yīng)該是一個不錯的選擇,這樣不必打斷關(guān)聯(lián)關(guān)系。如果是一般數(shù)據(jù)間的跨節(jié)點的關(guān)聯(lián),就必須打斷。
      需要特別說明的是:當(dāng)同時進行垂直和水平切分時,切分策略會發(fā)生一些微妙的變化。比如:在只考慮垂直切分的時候,被劃分到一起的表之間可以保持任意的關(guān)聯(lián)關(guān)系,因此你可以按“功能模塊”劃分表格,但是一旦引入水平切分之后,表間關(guān)聯(lián)關(guān)系就會受到很大的制約,通常只能允許一個主表(以該表ID進行散列的表)和其多個次表之間保留關(guān)聯(lián)關(guān)系,也就是說:當(dāng)同時進行垂直和水平切分時,在垂直方向上的切分將不再以“功能模塊”進行劃分,而是需要更加細(xì)粒度的垂直切分,而這個粒度與領(lǐng)域驅(qū)動設(shè)計中的“聚合”概念不謀而合,甚至可以說是完全一致,每個shard的主表正是一個聚合中的聚合根!這樣切分下來你會發(fā)現(xiàn)數(shù)據(jù)庫分被切分地過于分散了(shard的數(shù)量會比較多,但是shard里的表卻不多),為了避免管理過多的數(shù)據(jù)源,充分利用每一個數(shù)據(jù)庫服務(wù)器的資源,可以考慮將業(yè)務(wù)上相近,并且具有相近數(shù)據(jù)增長速率(主表數(shù)據(jù)量在同一數(shù)量級上)的兩個或多個shard放到同一個數(shù)據(jù)源里,每個shard依然是獨立的,它們有各自的主表,并使用各自主表ID進行散列,不同的只是它們的散列取模(即節(jié)點數(shù)量)必需是一致的。(本文著重介紹sharding的基本思想和理論上的切分策略,關(guān)于更加細(xì)致的實施策略和參考事例請參考我的另一篇博文:數(shù)據(jù)庫分庫分表(sharding)系列(一) 拆分實施策略和示例演示)
      1.事務(wù)問題:
      解決事務(wù)問題目前有兩種可行的方案:分布式事務(wù)和通過應(yīng)用程序與數(shù)據(jù)庫共同控制實現(xiàn)事務(wù)下面對兩套方案進行一個簡單的對比。
      方案一:使用分布式事務(wù)
      優(yōu)點:交由數(shù)據(jù)庫管理,簡單有效
      缺點:性能代價高,特別是shard越來越多時
      方案二:由應(yīng)用程序和數(shù)據(jù)庫共同控制
      原理:將一個跨多個數(shù)據(jù)庫的分布式事務(wù)分拆成多個僅處
      于單個數(shù)據(jù)庫上面的小事務(wù),并通過應(yīng)用程序來總控
      各個小事務(wù)。
      優(yōu)點:性能上有優(yōu)勢
      缺點:需要應(yīng)用程序在事務(wù)控制上做靈活設(shè)計。如果使用
      了spring的事務(wù)管理,改動起來會面臨一定的困難。
      2.跨節(jié)點Join的問題
      只要是時行切分,跨節(jié)點Join的問明是不可避免的。但是良好的設(shè)計和切分卻可以減少此類情況的發(fā)生。解決這一問題的普遍做法是分兩次查詢實現(xiàn)。在第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)的id,根據(jù)這些id發(fā)起第二次請求得到關(guān)聯(lián)數(shù)據(jù)。
      3.跨節(jié)點的count,order by,group by以及聚合函數(shù)問題
      這些是一類問題,因為它們都需要基于全部數(shù)據(jù)集合進行計算。多數(shù)的代理都不會自動處理合并工作。解決方案:與解決跨節(jié)點join問題的類似,分別在各個節(jié)點上得到結(jié)果后在應(yīng)用程序端進行合并。和join不同的是每個結(jié)點的查詢可以并行執(zhí)行,因此很多時候它的速度要比單一大表快很多。但如果結(jié)果集很大,對應(yīng)用程序內(nèi)存的消耗是一個問題。

    posted @ 2014-04-09 10:50 順其自然EVO 閱讀(591) | 評論 (0)編輯 收藏

    過濾XSS攻擊和SQL注入函數(shù)

    /**
    +----------------------------------------------------------
    * The goal of this function is to be a generic function that can be used to parse almost any input and     * render it XSS safe. For more information on actual XSS attacks, check out http://ha.ckers.org/xss.html. * Another excellent site is the XSS Database which details each attack and how it works.
    * XSS過濾
    +----------------------------------------------------------
    * @param mixed $value 變量
    +----------------------------------------------------------
    * @return mixed 過濾后的字符串
    +----------------------------------------------------------
    */
    function RemoveXSS($val) {
    // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
    // this prevents some character re-spacing such as <java\0script>
    // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some          // inputs
    $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);
    // straight replacements, the user should never need these since they're normal characters
    // this prevents like <IMG SRC=@avascript:alert('XSS')>
    $search = 'abcdefghijklmnopqrstuvwxyz';
    $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $search .= '1234567890!@#$%^&*()';
    $search .= '~`";:?+/={}[]-_|\'\\';
    for ($i = 0; $i < strlen($search); $i++) {
    // ;? matches the ;, which is optional
    // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
    // @ @ search for the hex values
    $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val);//with a ;
    // @ @ 0{0,7} matches '0' zero to seven times
    $val = preg_replace('/(�{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
    }
    // now the only remaining whitespace attacks are \t, \n, and \r
    $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
    $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
    $ra = array_merge($ra1, $ra2);
    $found = true; // keep replacing as long as the previous round replaced something
    while ($found == true) {
    $val_before = $val;
    for ($i = 0; $i < sizeof($ra); $i++) {
    $pattern = '/';
    for ($j = 0; $j < strlen($ra[$i]); $j++) {
    if ($j > 0) {
    $pattern .= '(';
    $pattern .= '(&#[xX]0{0,8}([9ab]);)';
    $pattern .= '|';
    $pattern .= '|(�{0,8}([9|10|13]);)';
    $pattern .= ')*';
    }
    $pattern .= $ra[$i][$j];
    }
    $pattern .= '/i';
    $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
    $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
    if ($val_before == $val) {
    // no replacements were made, so exit the loop
    $found = false;
    }
    }
    }
    return $val;
    }
    /*
    +----------------------------------------------------------
    * 函數(shù)名稱:inject_check()
    +----------------------------------------------------------
    * 函數(shù)作用:檢測提交的值是不是含有SQL注射的字符,防止注射,保護服務(wù)器安全
    +----------------------------------------------------------
    * @param mixed $sql_str: 提交的變量
    +----------------------------------------------------------
    * @return mixed 返回檢測結(jié)果,ture or false
    +----------------------------------------------------------
    */
    function inject_check($sql_str) {
    return $sql_str = preg_replace('select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile','', $sql_str);    // 進行過濾
    /*
    +----------------------------------------------------------
    * 函數(shù)名稱:escapeMysql()
    * SQL注入主要是提交不安全的數(shù)據(jù)給數(shù)據(jù)庫來達(dá)到攻擊目的。為了防止SQL注入攻擊,PHP自帶一個功能可以對輸入的字符串進行處理,可以在較底層對 * 輸入進行安全上的初步處理,也即Magic Quotes。(php.ini magic_quotes_gpc)。如果magic_quotes_gpc選項啟用,那么輸入的字符串    * 中的單引號,雙引號和其它一些字符前將會被自動加上反斜杠\。
    * 但Magic Quotes并不是一個很通用的解決方案,沒能屏蔽所有有潛在危險的字符,并且在許多服務(wù)器上Magic Quotes并沒有被啟用。所以,我們    * 還需要使用其它多種方法來防止SQL注入。許多數(shù)據(jù)庫本身就提供這種輸入數(shù)據(jù)處理功能。例如PHP的MySQL操作函數(shù)中有一個叫                 * mysql_real_escape_string()的函數(shù),可將特殊字符和可能引起數(shù)據(jù)庫操作出錯的字符轉(zhuǎn)義。
    +----------------------------------------------------------
    * 函數(shù)作用:檢測提交的值是不是含有SQL注射的字符,防止注射,保護服務(wù)器安全
    +----------------------------------------------------------
    * @param mixed $sql_str: 提交的變量
    +----------------------------------------------------------
    * @return mixed 返回檢測結(jié)果,ture or false
    +----------------------------------------------------------
    */
    function escapeMysql($el){
    if(is_array($el))
    {
    return   array_map("escapeMysql",   $el   );
    }else{
    /*如果Magic Quotes功用啟用    */
    if (!get_magic_quotes_gpc()) {
    $el = mysql_real_escape_string(trim($el));
    }
    $el    =    str_ireplace("%5d%5c", "'", $el);
    $el = str_replace("_", "\_", $el);    // 把 '_'過濾掉
    $el = str_replace("%", "\%", $el);    // 把 '%'過濾掉
    $el = nl2br($el);    // 回車轉(zhuǎn)換
    return   $el;
    }
    }
    /**
    +----------------------------------------------------------
    * 變量過濾
    +----------------------------------------------------------
    * @param mixed $value 變量
    +----------------------------------------------------------
    * @return mixed
    +----------------------------------------------------------
    */
    function var_filter_deep($value) {
    return $value;
    if(is_array($value))
    {
    return $value =   array_map("var_filter_deep",   $value   );
    }else{
    $value = RemoveXSS($value);
    //$value = inject_check($value);
    $value = escapeMysql($value);
    return $value;
    }
    }
    /*
    +----------------------------------------------------------
    * 函數(shù)名稱:verify_id()
    +----------------------------------------------------------
    * 函數(shù)作用:校驗提交的ID類值是否合法
    +----------------------------------------------------------
    * 參  數(shù):$id: 提交的ID值
    +----------------------------------------------------------
    * 返 回 值:返回處理后的ID
    +----------------------------------------------------------
    */
    function verify_id($id=null) {
    if (!$id) { exit('沒有提交參數(shù)!'); }    // 是否為空判斷
    elseif (inject_check($id)) { exit('提交的參數(shù)非法!'); }    // 注射判斷
    elseif (!is_numeric($id)) { exit('提交的參數(shù)非法!'); }    // 數(shù)字判斷
    $id = intval($id);    // 整型化
    return $id;
    }
    /**
    +----------------------------------------------------------
    * 變量安全過濾
    +----------------------------------------------------------
    * @static
    * @access public
    +----------------------------------------------------------
    * @return string
    +----------------------------------------------------------
    */
    function varFilter ()
    {
    $_SERVER = array_map(   "var_filter_deep", $_SERVER );
    $_REQUEST = array_map(   "var_filter_deep", $_REQUEST);
    $_POST    = array_map(   "var_filter_deep", $_POST   );
    $_GET     = array_map(   "var_filter_deep", $_GET    );
    $_COOKIE = array_map(   "var_filter_deep", $_COOKIE );
    //print_r($_POST);
    }

    posted @ 2014-04-09 10:43 順其自然EVO 閱讀(815) | 評論 (0)編輯 收藏

    LoadRunner 接口測試

    Action1()
    {
    int i;
    lr_rendezvous("rend");
    lr_start_transaction("get");
    for(i=0;i<11;i++)
    {
    web_url("get",
    "URL=http://{urlparam}",
    "Resource=1",
    "RecContentType=application/json",
    "Referer=",
    "Snapshot=t1.inf",
    LAST);
    }
    lr_end_transaction("get", LR_AUTO);
    lr_start_transaction("post");
    web_submit_data("post",
    "Action=http://api.zjol.com.cn/api/user_feedback",
    "Method=POST",
    "RecContentType=text/html",
    "Mode=HTML",
    ITEMDATA,
    "Name=session_id", "Value=4f59d9d14d405ae7367544af", ENDITEM,
    "Name=title", "Value=test_title", ENDITEM,
    "Name=content", "Value=test data", ENDITEM,
    LAST);
    web_submit_data("jpost",
    "Action=http://api.zjol.com.cn/api/client_log/batch",
    "Method=POST",
    "RecContentType=application/json",
    "Mode=HTML",
    ITEMDATA,
    "Name=session_id", "Value=4f59d9d14d405ae7367544af", ENDITEM,
    "Name=is_test", "Value=false", ENDITEM,
    "Name=logs", "Value=[{\"local_time\":1395051006337,\"log_level\":1,\"op_place\":0,\"op_type\":4001},{\"local_time\":1395051094555,\"log_level\":1,\"op_place\":0,\"op_type\":4002},{\"local_time\":1395051115432,\"log_level\":1,\"op_place\":0,\"op_type\":4001},{\"local_time\":1395051132291,\"log_level\":1,\"op_place\":0,\"op_target\":\"52e5f902cf81d754a434fb52\",\"op_type\":2004},{\"local_time\":1395051147817,\"log_level\":1,\"op_place\":0,\"op_type\":5000}]", ENDITEM,
    LAST);
    lr_end_transaction("post", LR_AUTO);
    return 0;
    }
      都用了web_submit_data函數(shù),包括存在JSON數(shù)據(jù),都能實現(xiàn)。  用web_custom_request函數(shù)就沒成功過。

    posted @ 2014-04-09 10:39 順其自然EVO 閱讀(402) | 評論 (0)編輯 收藏

    Appium自動化測試框架構(gòu)建

    Appium簡介
      Appium是一個開源、跨平臺的測試框架,可以用來測試原生及混合的移動端應(yīng)用。Appium支持iOS、Android及FirefoxOS平臺測試。Appium使用WebDriver的json wire協(xié)議,來驅(qū)動Apple系統(tǒng)的UIAutomation庫、Android系統(tǒng)的UIAutomator框架。
      相比其他的移動自動化測試工具,Appium測試由于調(diào)用了Selenium的client庫使其可以使用任意的語言,包括Python、Ruby、Node.js、Objective-C等。
      Appium下載與安裝
      可以去官方下載也可去github下,目前最新的是0.17.6版。當(dāng)然國內(nèi)的網(wǎng)盤里也有,這樣就不用fan.qiang了。下載后解壓即可使用,很方便。
      目前的Appium版本需.net4.5及以上支持,故要想使用Appium還需安裝.net4.5.1,可以去微軟下載.net4.5.1,當(dāng)然網(wǎng)盤里也有了,呵呵。
      由于Appium使用了Selenium來進行自動化測試,所以還需安裝Selenium,網(wǎng)盤里有下載,Selenium下載地址。下載后解壓,切換目錄到解壓目錄,然后執(zhí)行python setup.py install即可安裝Selenium,當(dāng)然如果您熟悉pip 也可以用pip install Selenium來安裝。
      安裝、配置Android模擬器
      我們打算在模擬器上使用appium進行自動化測試,故首先得下載安裝android開發(fā)環(huán)境,IDE開發(fā)環(huán)境配置好以后就可以通過eclipse創(chuàng)建一個android手機模擬器了。
      下載JDK與配置JDK
      下載JDK,下載之后雙擊壓縮包并安裝,一路默認(rèn)下去即可完成,jdk安裝到了C:\Java目錄下了,其下有兩個文件夾jdk1.6.0_13和jre6。
      配置jdk比較簡單將C:\Java\jdk1.6.0_13\bin目錄添加到系統(tǒng)環(huán)境變量path里,記住前加分號,之后確認(rèn)即可。
      怎樣測試java是否配置好?cmd之后鍵入java -verison
      下載android開發(fā)環(huán)境ADT-bundle
      可以去Google下載也可以去網(wǎng)盤下載android的集成開發(fā)環(huán)境。下載后解壓到c:\android目錄下就行了。
      配置ADT
      將解壓目錄下的sdk下的tools和platform-tools目錄添加到系統(tǒng)環(huán)境變量path里,記住前加分號,之后確認(rèn)即可。
      怎樣測試android的ADT是否配置好?進入c:\android\eclipse目錄雙擊eclipse.exe,看能否正常啟動、使用。
      新AVD模擬器
      啟動eclipse,點擊Eclipse軟件的Windows菜單,選擇其下的Android Virtual Device Manager菜單項,進入Android Virtual Device Manager其對話框后,點擊左側(cè)New按鈕可新建android手機模擬器。在Create new Android Virtual Device Manager對話框的name文本框內(nèi)給要創(chuàng)建的模擬器起個名字,例如testAVD01。在Device列表框內(nèi)選擇2.7 QVGA 240 X320 ldpi,在選擇了Device后,target列表框自動選擇了android 4.4 API Level 19{現(xiàn)在已安裝的開發(fā)環(huán)境里只有一套API,讀者可自行安裝其他API,屆時可任選其他API作為自己測試平臺}默認(rèn)即可,其他選項此時可以不做選擇默認(rèn)設(shè)置即可,點擊對話框的OK按鈕確認(rèn),即可創(chuàng)建Android 模擬器。
      啟動android模擬器
      cmd之后鍵入 emulator @testAVD01,等待數(shù)秒之后android手機模擬器啟動。
      安裝、配置Python
      這步比較簡單,下載Python后默認(rèn)安裝即可。配置只需把c:\python27目錄加到系統(tǒng)環(huán)境變量path后即可,記住前加分號。cmd之后鍵入python如果見到3個大于號即證明python安裝配置成功。Appium自動化測試流程
      啟動android手機模擬器
      cmd之后鍵入 emulator @testAVD01,等待數(shù)秒之后android手機模擬器啟動。
      另起一個cmd鍵入adb devices查看模擬器是否正常啟動了。
      啟動Appium
      進入appium解壓目錄,雙擊appium.exe文件,點擊launch即可。
      基于Appium的Python自動化測試
      編寫代碼
    from selenium import webdriver
    # Returns abs path relative to this file and not cwd
    PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
    )
    desired_caps = {}
    desired_caps['device'] = 'android'
    desired_caps['browserName'] = ''
    desired_caps['version'] = '4.2'
    desired_caps['app-package'] = 'com.android.calculator2'
    desired_caps['app-activity'] = '.Calculator'
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    # 點擊計算器上的數(shù)字和運算符
    el = driver.find_element_by_name("1")
    el.click()
    el = driver.find_element_by_name("5")
    el.click()
    el = driver.find_element_by_name("9")
    el.click()
    el = driver.find_element_by_name("delete")
    el.click()
    el = driver.find_element_by_name("9")
    el.click()
    el = driver.find_element_by_name("5")
    el.click()
    el = driver.find_element_by_name("+")
    el.click()
    el = driver.find_element_by_name("6")
    el.click()
    el = driver.find_element_by_name("=")
    el.click()
    driver.quit()
      執(zhí)行代碼
      另起cmd,切到python代碼所在目錄,執(zhí)行python xxx.py即可見模擬器在被操作了。

    posted @ 2014-04-09 10:32 順其自然EVO 閱讀(7359) | 評論 (0)編輯 收藏

    QTP VBScript RegExp對象的運用

     下面來講講RegExp對象:
      Vbs提供了針對正則表達(dá)式的一個非常實用的類,就是RegExp
    Global屬性:代表全局匹配
    IgnoreCase屬性:大小寫忽略
    Pattern屬性:正則表達(dá)式
    Execute方法:匹配搜索,返回匹配結(jié)果集合
    Replace方法:匹配代替,返回替代匹配結(jié)果
    Test方法:測試匹配,返回布爾類型
      下面舉幾個實例:
    '判斷正則匹配是否正確
    'msgbox (IsRegMatch("a123","http://www.123.456.com"))
    Function IsRegMatch(patrn,str)
    Dim regEx
    Set regEx = New RegExp
    regEx.Pattern = patrn
    regEx.IgnoreCase = False
    IsRegMatch = regEx.Test(str)
    Set regEx = nothing
    End Function
    '替換匹配字符串
    'msgbox (ReplaceRegMatch("9","loader runner 9.0, qtp 9.0","10"))
    Function ReplaceRegMatch(patrn,str,replaceStr)
    Dim regEx
    Set regEx = New RegExp
    regEx.Pattern = patrn
    regEx.IgnoreCase = False
    regEx.Global = True   'false的時候只會替換第一個匹配的字符串。若為true則會替換所有匹配的字符串
    ReplaceRegMatch = regEx.Replace(str,replaceStr)
    End Function
    '返回匹配內(nèi)容
    'returnRegMatch "qtp .","qtp 1 qtp 2 qtp3 qtp 4"
    Function ReturnRegMatch(patrn,str)
    Dim regEx,matches,match
    Set regEx = New RegExp
    regEx.Pattern = patrn
    regEx.IgnoreCase = true
    regEx.Global = true  '打開全局搜索
    Set matches = regEx.Execute(str)
    For Each match in matches
    print cstr(match.firstIndex) + " " + match.value + " " + cstr(match.length)
    Next
    End Function

    posted @ 2014-04-09 10:31 順其自然EVO 閱讀(458) | 評論 (0)編輯 收藏

    項目中遇到的問題

     產(chǎn)品總算上線了,歷時兩個半月的時間,出了內(nèi)測,公測,beta版本,1.0.1版本,中間有段時間累得夠嗆,但上線之后,感覺努力還是值的。
      在整個測試過程中,遇到了一些問題,及在遇到這些問題后所采取的措施
      1. 提測質(zhì)量差
      問題描述:第一個提測版本差,有些均未通過冒煙測試
      問題分析
      A. 版本提測質(zhì)量差,但基于發(fā)布時間已在,因此,在提測差時就開始測試
      提測質(zhì)量差的點:- 基于上每項功能的完成度都不高 - 有些功能均未實現(xiàn) -
      B. 新的團隊,團隊處于磨合期
      C. 在提測時,對提測要求不明確,在時間點到后,匆忙提測
      解決方式:
      明確版本提測要求,并且開發(fā)得到了足夠的時間。
      2. 版本控制
      問題描述:
      最初階段,每天出一個版本,基于新版本測試,記錄每個版本上測試的功能。版本過于頻繁,質(zhì)量把控不好
      問題分析:
      A. 基于版本提測質(zhì)量差,而且每天出一個版本,差上加差,
      B. 雖然記錄每個版本上測試的功能,但仍然無法把控當(dāng)前版本的質(zhì)量狀況。
      解決方式:暫停每天發(fā)布一個版本
      前期:將全功能版本作為下一個版本發(fā)布目標(biāo),但由于一些功能并沒有完成,因而,全功能版本分成了好幾個階段
      后期:以測試一輪周期,發(fā)布最新版本
      3. 功能反復(fù)
      問題描述:在上一個版本是OK的功能,在新版本中功能失常
      功能反復(fù)分兩點:一是大功能反復(fù), 二是小功能(如:某個bug)反復(fù)
      問題分析:
      大功能反復(fù):情況主要發(fā)生成項目前期和中期
      A. 功能未完成,在完善功能時,未考慮到與該功能相關(guān)的點
      B. 在提測之后,發(fā)現(xiàn)一些問題,導(dǎo)致了整個模塊重構(gòu),重構(gòu)后導(dǎo)致了問題的反復(fù)
      小功能反復(fù):這個情況主要發(fā)生在項目中后期
      A. 因為項目里的部分開發(fā)是外援的,在項目中期時,撤出了團隊,新接手的人員,對代碼不熟悉,在修改bug時,經(jīng)常出來顧此失彼
      B. 開發(fā)小一在修改代碼時,動到了小二的代碼,導(dǎo)致了小二出了問題
      解決方式:
      對大功能反復(fù),是這么處理:冒煙測試由開發(fā)來完成,冒煙通過后,再交由測試
      對小功能反復(fù) ,沒有有效的處理方式,測試這邊可以做的是,加強測試,這個問題,在發(fā)布前夕好了很多,但問題仍然存在  4. 需求不明確,前后不一致
      問題描述:需求不明確,特別在一些邊界,各端統(tǒng)一上
      問題分析:
      A. 交互文檔經(jīng)歷6任交互,最后一任交互只參與兩個模塊的定義,現(xiàn)任交互對于以往交互了解不夠深入
      B. 產(chǎn)品提測時,交互驗證不足
      解決方式:
      由于項目已提測,因此在整個周期里,對于交互需求方面的疑問直接找相關(guān)人員去確認(rèn)。
      在后期的小版本中,我們把這類問題盡量控制在提測之前(詳見小版本里的改進與問題)
      5. 測試和開發(fā)信息不對稱
      問題描述:測試獲取到的消息,與產(chǎn)品實現(xiàn)的方式不一致,如:有的功能定義了,但產(chǎn)品并未實現(xiàn)或?qū)崿F(xiàn)方式與定義不一致
      問題分析:
      A. 在開發(fā)階段,測試并未參與討論需求,還在其他項目里
      B. 需求重新確認(rèn)后,沒有及時通知測試
      解決方式:
      強調(diào)消息需要通知到測試,現(xiàn)在階段,如果因這種類型而引起的問題,將建ticket,指派給相關(guān)人員
      小版本里的改進與問題
      現(xiàn)存在問題:
      1. 現(xiàn)對Release版本會做RC checklist, 進行最后版本的質(zhì)量控制,
      但會存在一些問題,在小版本提測時,就已經(jīng)存在,而冒煙測試是測不到的,在最后做checklist時,才發(fā)現(xiàn)
      改進點:
      1. 需求疑問在提測之前盡量提出,并且通知到開發(fā),在開發(fā)階段便把該問題解決
      測試在開發(fā)階段跟蹤產(chǎn)品進度
      在寫測試用例時,就把問題拋出。
      2. 提測流程:
      對功能方面的ticket,交互在提測之前便在開發(fā)機器上驗證,通過后再提測
      把不符合交互預(yù)期的問題,在提測之前更改,節(jié)約了時間,避免問題在提測后才提出

    posted @ 2014-04-09 10:28 順其自然EVO 閱讀(246) | 評論 (0)編輯 收藏

    Linux crontab 實現(xiàn)每秒執(zhí)行

     linux crontab 命令,最小的執(zhí)行時間是一分鐘。如需要在小于一分鐘內(nèi)重復(fù)執(zhí)行,可以有兩個方法實現(xiàn)。
      1.使用延時來實現(xiàn)每N秒執(zhí)行
      創(chuàng)建一個php做執(zhí)行動作,非常簡單,就是把當(dāng)前時間寫入log。
      <?php
      file_put_contents('/home/fdipzone/php/crontab/run.log', date('Y-m-d H:i:s')."\r\n", FILE_APPEND);
      ?>
      crontab -e 輸入以下語句,然后 :wq 保存退出。
    * * * * * php /home/fdipzone/php/crontab/tolog.php
    * * * * * sleep 10; php /home/fdipzone/php/crontab/tolog.php
    * * * * * sleep 20; php /home/fdipzone/php/crontab/tolog.php
    * * * * * sleep 30; php /home/fdipzone/php/crontab/tolog.php
    * * * * * sleep 40; php /home/fdipzone/php/crontab/tolog.php
    * * * * * sleep 50; php /home/fdipzone/php/crontab/tolog.php
      使用 tail -f 查看執(zhí)行情況,可以見到log每10秒被寫入一條記錄。
    fdipzone@ubuntu:~$ tail -f /home/fdipzone/php/crontab/run.log
    2014-03-31 21:47:01
    2014-03-31 21:47:11
    2014-03-31 21:47:21
    2014-03-31 21:47:31
    2014-03-31 21:47:41
    2014-03-31 21:47:51
    2014-03-31 21:48:01
      原理:通過延時方法 sleep N  來實現(xiàn)每N秒執(zhí)行。
      注意:
      60必須能整除間隔的秒數(shù)(沒有余數(shù)),例如間隔的秒數(shù)是2,4,6,10,12等。
      如果間隔的秒數(shù)太少,例如2秒執(zhí)行一次,這樣就需要在crontab 加入60/2=30條語句。不建議使用此方法,可以使用下面介紹的第二種方法。
      2.編寫shell腳本實現(xiàn)
    crontab.sh
    #!/bin/bash
    step=2 #間隔的秒數(shù),不能大于60
    for (( i = 0; i < 60; i=(i+step) )); do
    $(php '/home/fdipzone/php/crontab/tolog.php')
    sleep $step
    done
    exit 0
      crontab -e 輸入以下語句,然后:wq 保存退出。
      # m h  dom mon dow   command
      * * * * * /home/fdipzone/php/crontab/crontab.sh

      使用 tail -f 查看執(zhí)行情況,可以見到log每2秒被寫入一條記錄。
    fdipzone@ubuntu:~/php/crontab$ tail -f run.log
    2014-03-31 22:23:01
    2014-03-31 22:23:03
    2014-03-31 22:23:06
    2014-03-31 22:23:08
    2014-03-31 22:23:10
    2014-03-31 22:23:12
    2014-03-31 22:23:14
    2014-03-31 22:23:16
    2014-03-31 22:23:18
    2014-03-31 22:23:20
    2014-03-31 22:23:22
    2014-03-31 22:23:25
    2014-03-31 22:23:27
    2014-03-31 22:23:29
    2014-03-31 22:23:31
    2014-03-31 22:23:33
    2014-03-31 22:23:35
    2014-03-31 22:23:37
    2014-03-31 22:23:39
    2014-03-31 22:23:41
    2014-03-31 22:23:44
    2014-03-31 22:23:46
    2014-03-31 22:23:48
    2014-03-31 22:23:50
    2014-03-31 22:23:52
    2014-03-31 22:23:54
    2014-03-31 22:23:56
    2014-03-31 22:23:58
    2014-03-31 22:24:00
      原理:在sh使用for語句實現(xiàn)循環(huán)指定秒數(shù)執(zhí)行。
      注意:如果60不能整除間隔的秒數(shù),則需要調(diào)整執(zhí)行的時間。例如需要每7秒執(zhí)行一次,就需要找到7與60的最小公倍數(shù),7與60的最小公倍數(shù)是420(即7分鐘)。
      則 crontab.sh step的值為7,循環(huán)結(jié)束條件 i<420, crontab -e可以輸入以下語句來實現(xiàn)
      # m h  dom mon dow   command
      */7 * * * * /home/fdipzone/php/crontab/crontab.sh

    posted @ 2014-04-08 10:58 順其自然EVO 閱讀(3642) | 評論 (1)編輯 收藏

    MySQL數(shù)據(jù)庫設(shè)置遠(yuǎn)程訪問

      1、修改localhost
      更改 "mysql" 數(shù)據(jù)庫里的 "user" 表里的 "host" 項,從"localhost"改成"%"
      mysql>use mysql;
      mysql>update user set host = '%' where user = 'root';
      mysql>select host, user from user;
      mysql>FLUSH PRIVILEGES;
      2、指定授權(quán)
      使用myuser/mypassword從任何主機連接到mysql服務(wù)器:
      GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
      使用myuser/mypassword從ip為192.168.225.166的主機連接到mysql服務(wù)器:
      GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'192.168.225.166' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
      3、泛授權(quán)
      mysql -h localhost -u root
      mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; //賦予任何主機上以root身份訪問數(shù)據(jù)的權(quán)限
      mysql>FLUSH PRIVILEGES;

    posted @ 2014-04-08 10:57 順其自然EVO 閱讀(163) | 評論 (0)編輯 收藏

    使用PDO查詢mysql避免SQL注入

     使用傳統(tǒng)的 mysql_connect 、mysql_query方法來連接查詢數(shù)據(jù)庫時,如果過濾不嚴(yán)緊,就有SQL注入風(fēng)險。雖然可以用mysql_real_escape_string()函數(shù)過濾用戶提交的值,但是也有缺陷。而使用PHP的PDO擴展的 prepare 方法,就可以避免sql injection 風(fēng)險。
      PDO(PHP Data Object) 是PHP5新加入的一個重大功能,因為在PHP 5以前的php4/php3都是一堆的數(shù)據(jù)庫擴展來跟各個數(shù)據(jù)庫的連接和處理,如 php_mysql.dll。 PHP6中也將默認(rèn)使用PDO的方式連接,mysql擴展將被作為輔助 。官方地址:http://php.net/manual/en/book.pdo.php
      1. PDO配置
      使用PDO擴展之前,先要啟用這個擴展,php.ini中,去掉"extension=php_pdo.dll"前面的";"號,若要連接數(shù)據(jù)庫,還需要去掉與PDO相關(guān)的數(shù)據(jù)庫擴展前面的";"號(一般用的是php_pdo_mysql.dll),然后重啟Apache服務(wù)器即可。
      extension=php_pdo.dll
      extension=php_pdo_mysql.dll
      2. PDO連接mysql數(shù)據(jù)庫
      $dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password");
      默認(rèn)不是長連接,若要使用數(shù)據(jù)庫長連接,可以在最后加如下參數(shù):
      $dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password","array(PDO::ATTR_PERSISTENT => true) ");
      $dbh = null; //(釋放)
      3. PDO設(shè)置屬性
      PDO有三種錯誤處理方式:
      PDO::ERrmODE_SILENT不顯示錯誤信息,只設(shè)置錯誤碼
      PDO::ERrmODE_WARNING顯示警告錯
      PDO::ERrmODE_EXCEPTION拋出異常
      可通過以下語句來設(shè)置錯誤處理方式為拋出異常
      $db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);
      因為不同數(shù)據(jù)庫對返回的字段名稱大小寫處理不同,所以PDO提供了PDO::ATTR_CASE設(shè)置項(包括PDO::CASE_LOWER,PDO::CASE_NATURAL,PDO::CASE_UPPER),來確定返回的字段名稱的大小寫。
      通過設(shè)置PDO::ATTR_ORACLE_NULLS類型(包括PDO::NULL_NATURAL,PDO::NULL_EmpTY_STRING,PDO::NULL_TO_STRING)來指定數(shù)據(jù)庫返回的NULL值在php中對應(yīng)的數(shù)值。
      4. PDO常用方法及其應(yīng)用
      PDO::query() 主要是用于有記錄結(jié)果返回的操作,特別是SELECT操作
      PDO::exec() 主要是針對沒有結(jié)果集合返回的操作,如INSERT、UPDATE等操作
      PDO::prepare() 主要是預(yù)處理操作,需要通過$rs->execute()來執(zhí)行預(yù)處理里面的SQL語句,這個方法可以綁定參數(shù),功能比較強大(防止sql注入就靠這個)
      PDO::lastInsertId() 返回上次插入操作,主鍵列類型是自增的最后的自增ID
      PDOStatement::fetch() 是用來獲取一條記錄
      PDOStatement::fetchAll() 是獲取所有記錄集到一個集合
      PDOStatement::fetchColumn() 是獲取結(jié)果指定第一條記錄的某個字段,缺省是第一個字段
      PDOStatement::rowCount() :主要是用于PDO::query()和PDO::prepare()進行DELETE、INSERT、UPDATE操作影響的結(jié)果集,對PDO::exec()方法和SELECT操作無效。  5.PDO操作MYSQL數(shù)據(jù)庫實例
    <?php
    $pdo = new PDO("mysql:host=localhost;dbname=mydb","root","");
    if($pdo -> exec("insert into mytable(name,content) values('fdipzone','123456')")){
    echo "insert success";
    echo $pdo -> lastinsertid();
    }
    ?>
    <?php
    $pdo = new PDO("mysql:host=localhost;dbname=mydb","root","");
    $rs = $pdo -> query("select * from table");
    $rs->setFetchMode(PDO::FETCH_ASSOC); //關(guān)聯(lián)數(shù)組形式
    //$rs->setFetchMode(PDO::FETCH_NUM); //數(shù)字索引數(shù)組形式
    while($row = $rs -> fetch()){
    print_r($row);
    }
    ?>
    <?php
    foreach( $db->query( "SELECT * FROM table" ) as $row )
    {
    print_r( $row );
    }
    ?>
      統(tǒng)計有多少行數(shù)據(jù):
    <?php
    $sql="select count(*) from table";
    $num = $dbh->query($sql)->fetchColumn();
    ?>
      prepare方式:
    <?php
    $query = $dbh->prepare("select * from table");
    if ($query->execute()) {
    while ($row = $query->fetch()) {
    print_r($row);
    }
    }
    ?>
      prepare參數(shù)化查詢:
    <?php
    $query = $dbh->prepare("select * from table where id = ?");
    if ($query->execute(array(1000))) {
    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
    print_r($row);
    }
    }
    ?>
      使用PDO訪問MySQL數(shù)據(jù)庫時,真正的real prepared statements 默認(rèn)情況下是不使用的。為了解決這個問題,你必須禁用 prepared statements的仿真效果。下面是使用PDO創(chuàng)建鏈接的例子:
      <?php
      $dbh = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'pass');
      $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
      ?>
      setAttribute()這一行是強制性的,它會告訴 PDO 禁用模擬預(yù)處理語句,并使用 real parepared statements 。這可以確保SQL語句和相應(yīng)的值在傳遞到mysql服務(wù)器之前是不會被PHP解析的(禁止了所有可能的惡意SQL注入攻擊)。
      雖然你可以配置文件中設(shè)置字符集的屬性(charset=utf8),但是需要格外注意的是,老版本的 PHP( < 5.3.6)在DSN中是忽略字符參數(shù)的。
      完整的代碼使用實例:
    <?php
    $dbh = new PDO("mysql:host=localhost; dbname=mydb", "root", "pass");
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果
    $dbh->exec("set names 'utf8'");
    $sql="select * from table where username = ? and password = ?";
    $query = $dbh->prepare($sql);
    $exeres = $query->execute(array($username, $pass));
    if ($exeres) {
    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
    print_r($row);
    }
    }
    $dbh = null;
    ?>
      上面這段代碼就可以防范sql注入。為什么呢?
      當(dāng)調(diào)用 prepare() 時,查詢語句已經(jīng)發(fā)送給了數(shù)據(jù)庫服務(wù)器,此時只有占位符 ? 發(fā)送過去,沒有用戶提交的數(shù)據(jù);當(dāng)調(diào)用到 execute()時,用戶提交過來的值才會傳送給數(shù)據(jù)庫,它們是分開傳送的,兩者獨立的,SQL攻擊者沒有一點機會。
      但是我們需要注意的是以下幾種情況,PDO并不能幫助你防范SQL注入。
      不能讓占位符 ? 代替一組值,這樣只會獲取到這組數(shù)據(jù)的第一個值,如:
      select * from table where userid in ( ? );
      如果要用in來查找,可以改用find_in_set()實現(xiàn)
      $ids = '1,2,3,4,5,6';
      select * from table where find_in_set(userid, ?);
      不能讓占位符代替數(shù)據(jù)表名或列名,如:
      select * from table order by ?;
      不能讓占位符 ? 代替任何其他SQL語法,如:
      select extract( ? from addtime) as mytime from table;

    posted @ 2014-04-08 10:50 順其自然EVO 閱讀(197) | 評論 (0)編輯 收藏

    僅列出標(biāo)題
    共394頁: First 上一頁 128 129 130 131 132 133 134 135 136 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 白白色免费在线视频| 亚洲日韩国产欧美一区二区三区| 亚洲人成亚洲精品| 亚洲免费视频网址| 亚洲国产成人精品无码区花野真一 | 午夜无遮挡羞羞漫画免费| 免费大片黄手机在线观看| 亚洲无码在线播放| 亚洲春色另类小说| 朝桐光亚洲专区在线中文字幕 | 免费v片在线观看无遮挡| 亚洲男人的天堂www| 久久精品国产亚洲av麻豆蜜芽| 国产精品亚洲专一区二区三区| 成人网站免费大全日韩国产| 亚洲国产精品免费在线观看| 国内外成人免费视频| 国产亚洲精品久久久久秋霞| 亚洲视频免费在线播放| 成人免费无码大片A毛片抽搐色欲| 国产亚洲综合视频| 99精品视频免费| 一区在线免费观看| 亚洲AV成人无码天堂| 国产精品亚洲精品爽爽| 青柠影视在线观看免费高清 | 久久精品国产亚洲AV网站| 亚洲伊人久久大香线焦| 乱爱性全过程免费视频| 永久免费视频网站在线观看| 一区国严二区亚洲三区| 亚洲美女中文字幕| 深夜a级毛片免费视频| 2021精品国产品免费观看| 亚洲日韩国产精品乱| 亚洲a级在线观看| a级毛片免费全部播放| 免费无码又爽又刺激高潮| 无码久久精品国产亚洲Av影片| 亚洲成a∨人片在无码2023| 暖暖在线视频免费视频|