我們再來討論如何開發安全的web應用。網路上大部分資源都是開放,免費的。但是有些資源只需要特定的使用者才能訪問,例如一個論壇只有註冊使用者才能發言,管理員才能管理背景程式。為了讓不同使用者訪問不同資源,就需要採用安全機制來保護web應用程式的資源,避免關鍵資訊被未授權使用者訪問。
驗證機制
在servlet規範中,定義了四種驗證使用者的機制。
HTTP Basic Authentication
Http基本驗證是在HTTP 1.0中定義的、基於使用者名稱和密碼驗證機制。當web瀏覽器請求受保護的資源時,web伺服器會彈出一個對話方塊,讓使用者輸入使用者名稱和密碼。web用戶端從使用者處得到使用者名稱和密碼,然後傳給伺服器。伺服器負責驗證,如果密碼正確,伺服器將發送使用者所請求的資源。
HTTP Digest Authentication
和HTTP基本驗證相似,HTTP摘要驗證也是基於使用者名稱和密碼來驗證使用者的,不同的是,使用摘要驗證,使用者密碼是以加密的形式(對密碼採用MD5摘要演算法)傳輸的,這比採用Base64編碼要安全的多。
HTTP Client Authentication
HTTPS(Secure HTTP)是在SSL(Secure Socket Layer,安全通訊端)之上的HTTP協議。SSL是1995年由網景公司提出的一種安全性通訊協定,用於瀏覽器通訊端和伺服器通訊端之間建立一個安全的串連。SSL由兩個子協議組成,一個用於建立安全的串連,一個使用安全的串連。當建立安全連線之後,通訊雙方使用同一個工作階段金鑰對傳輸的資訊進行加密。HTTPS用戶端驗證主要在電子商務應用程式中使用。
Form Baesd Authentication
基於表單的驗證類似於基本驗證。不同的是,基於表單的驗證使用定製的HTML表單讓使用者輸入使用者名稱和密碼,而不是使用瀏覽器的彈出對話方塊。
聲明式安全
聲明式安全是在web.xml檔案中指定web應用程式的安全處理機制,這使得一個web應用程式無須修改任何原始碼就可以獲得安全性。預設情況下,web應用程式的所有資源對每個人都是開放訪問的。通過在web.xml中配置<security-constraint>和<login-config>元素來限制對資源的訪問。
<?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <!-- Define a Security Constraint on this Application --> <!-- NOTE: None of these roles are present in the default users file --> <security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>*.html</url-pattern> <url-pattern>*.jsp</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint> <!-- Define the Login Configuration for this Application --> <login-config> <auth-method>BASIC</auth-method> <realm-name>Tomcat Manager Application</realm-name> </login-config> <!-- Security roles referenced by this web application --> <security-role> <role-name>admin</role-name> </security-role> <security-role> <role-name>manager</role-name> </security-role></web-app>
如果在<web-resource-collection>元素下沒有使用<url-pattern>元素,那意味著對所有的HTTP方法都要施加安全限制,如果使用了該元素,則只對指定的HTTP方法施加安全限制。
<auth-constraint>元素指定可以訪問受保護資源的角色。<role-name>指定角色的名字,這二個名字必須是在<security-role>中指定的角色名稱,或者使用保留角色名稱“*”,表示web應用程式中所有角色。如果在 <auth-constraint>元素中沒有指定<role-name>子項目,那麼表示在任何情況下,沒有任何使用者可以訪問受保護的資源,如果定義了<role-name>子項目,則其指定的使用者可以訪問受保護的資源。如果沒有使用 <auth-constraint>元素,那麼容器允許使用者不經驗證就訪問受保護的資源。
<login-config>元素用於指定web應用程式使用的驗證機制。<auth-method>元素配置web應用程式驗證的機制,該元素的值必須是BASIC,DIGEST,FORM,CLIENT-CERT其中之一,或者是產品供應商指定的驗證模式。除了FORM外,其他3種驗證只需要在<auth-method>中配置即可。
程式式安全
在日常應用中,我們可能需要多個使用者或者多個角色都有許可權訪問某個資源,這樣更細粒度的安全控制,採用聲明式安全無法做到。此時,我們可以在程式碼中進一步實現細粒度的安全控制。程式式安全由HttpServletRequest介面中定義的三個方法組成,如下所示:
Public String getRemoteUser()//如果使用者已被驗證,該方法返回使用者的登入名稱。否則,返回null。Public java.security.Principal getUserPrincipal()//返回一個Principal對象,該對象包含了當前已經驗證的使用者名稱,如果還沒被驗證,返回null。Public boolean isUserInRole(String role)//判斷已驗證的使用者角色是否屬於指定角色,如果使用者還沒有被驗證,返回null。
SQL注入攻擊的防範
web應用程式的安全涉及多個方面,前面講述的是通過驗證和授權來防止未授權的使用者訪問受保護的資源。但有時候,安全問題往往是由系統本身的漏洞或程式員的疏忽引起的。例如,下面一段代碼:
String name = request.getParameter("username");String passwd = request.getParameter("password");...Statement stmt = conn.createStatement();String sql = "select username from admins where username ="+"'"+name+"' and password = '"+passwd+"'";ResultSet rs = stmt.executeQuery(sql);while(rs.next()) {...}...
如果使用者名稱輸入“shan”,密碼輸入”1234“,則會構造如下sql語句:
select username from admins where username ='shan' and password = '1234'
如果一個惡意使用者通過查看網頁源碼,知道了表單中輸入使用者名稱的文本域和口令域的名字,直接在瀏覽器網址欄輸入”http://www.test.com/login.jsp?username=abcd&password=1111 or '1'='1'“,於是就順利的訪問了管理頁面。為什麼隨便一個使用者名稱和密碼就能訪問呢?我們查看一下構造的sql語句就明白了。如下:
select username from admins where username ='shan' and password = '1234' or '1'='1'
最後的'1'='1'是恒等條件。所以這個惡意使用者利用了sql語句的特點,構造了一個特殊查詢,讓原本不成立的語句就變得成立。這就是sql注入攻擊的一個例子。
在java中,要防止上述情況的發生,只需要用PreparedStatement取代Statement即可。所以在實際應用中,要盡量使用PreparedStatement。
轉載請註明出處:http://blog.csdn.net/iAm333