Java安全基礎之Servlet核心技術
因為在實習中,文章更新速度可能有點慢,初學JAVA安全,內容如有不恰當的地方,歡迎各位大佬指正。
今天寫一下Servlet的一些核心技術,后面更新完Filter之后我會對這兩個進行一個總結。
了解Servlet知識對后續的框架審計有一定的幫助。代碼審計中我們可以選擇Servlet入手,也可以選擇從漏洞點反推出Http請求的入口地址。
一、Servlet的配置
不同的版本的Servlet配置不同,Servlet3.0之前的版本都是在web.xml中配置的,而Servlet3.0之后的版本則使用更為便捷的注解方式來配置。此外,不同版本的Servlet所需的Java/JDK版本也不相同。
1.1、Servlet的配置-基于web.xml
<servlet>—— 聲明servlet配置入口
<description>—— 聲明servlet描述信息
<display-name>——— 定義WEB
<servlet-name>—— 聲明Servlet名稱以便在后面的映射時使用
<servlet-class>—— 指定當前servlet對應的類的路徑
<servlet-mapping>—— 注冊組件訪問配置的路徑入口
<servlet-name>—— 指定上文配置的Servlet的名稱
<url-pattern>—— 指定配置這個組件的訪問路徑
二、Servlet的訪問流程
我們以如下的配置文件舉例:
首先在瀏覽器地址欄中輸入user,即訪問url-pattern標簽中的值,然后瀏覽器發起請求,服務器通過servlet-mapping標簽中找到文件名為user的url-pattern,通過其對應的servlet-name尋找servlet標簽中servlet-name相同的servlet,再通過servlet標簽中servlet-name,獲取servlet-class參數,最終得到具體的class文件路徑,繼而執行servlet-class標簽中class文件的邏輯。
從上述過程中可以看出,servlet和servlet-mapping中都含有<servlet-name></servlet-name>標簽,其主要原因是通過servlet-name作為紐帶,將servlet-class和url-pattern構成聯系,從而使url映射到servlet-class所指定的類中執行相應邏輯。
首先在瀏覽器地址欄中輸入user,即訪問url-pattern標簽中的值,然后瀏覽器發起請求,服務器通過servlet-mapping標簽中找到文件名為user的url-pattern,通過其對應的servlet-name尋找servlet標簽中servlet-name相同的servlet,再通過servlet標簽中servlet-name,獲取servlet-class參數,最終得到具體的class文件路徑,繼而執行servlet-class標簽中class文件的邏輯。
從上述過程中可以看出,servlet和servlet-mapping中都含有<servlet-name></servlet-name>標簽,其主要原因是通過servlet-name作為紐帶,將servlet-class和url-pattern構成聯系,從而使url映射到servlet-class所指定的類中執行相應邏輯。
三、Servlet的接口方法
HTTP有8中請求方式,分別為,GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE以及CONNECT方法.與此類似,Servlet接口中也對于著響應的請求接口:GET、POST、HEAD、PUT、DELETE、OPTIONS以及TRACE,這些接口對應著請求類型,service()方法會檢查HTTP請求類型,然后在適當的時候調用doGet、doPost、doPost、doPut、doDelete等方法。
3.1、Servlet的接口方法 - init()接口
在Servlet實例化后,Servlet容器會巧用init()方法來初始化該對象,主要是為例使Servlet對象在處理客戶請求錢可以完成一些初始化工作,例如建立數據庫的連接,獲取配置信息等。init()方法在第一次創建servlet時被調用,在后續每次用戶請求時不在被調用。
在init()方法中有一個ServletConfig參數,ServletConfig代表的是配置信息,即在web.xml中配置的信息。
3.2、Servlet的接口方法 - service()接口
service()方法是執行實際任務的主要方法,Servlet容器(即web服務器)調用service()方法來處理來自客戶端(瀏覽器)的請求,并將格式化的響應寫回給客戶端,每次服務器接收到一個servlet請求時,服務器會產生一個新的線程并調用服務。要注意的是,在service()方法被Servlet容器調用之前,必須確保init()方法正確完成。
一般來說service方法是不需要重寫的,因為在HttpServlet中已經有了很好的實現,它會根據請求的方法名(GET,POST),調用doGet,doPos以及其他的doXXX方法,也就是說service是用來轉向的,所以我們一般寫一個servlet,只需要重寫doGet或者doPost就可以了。
3.3、Servlet的接口方法 - doGet() && doPost()接口
doGet()等方法根據HTTP的不同請求調用不同的方法,如果HTTP得到一個來自URL的GET請求,就會調用doGet()方法;如果得到的是一個POST請求,就會調用doPost()方法。
在servlet中默認情況下,無論你是get還是post提交過來都會經過service()方法來處理,然后轉向到doGet或者是doPost方法。
下面是自動生成的doGet()和doPost方法。
3.4、Servlet的接口方法 - 其他接口
destory()接口
當Servlet容器檢測到一個Servlet對象應該從服務中被移除時,就會調用該對象的destroy()方法,以便Servlet對象釋放它所使用的資源,保存數據到持久存儲設備中,例如將內存中的數據保存到數據庫中、關閉數據庫連接、停止后臺線程、把Cookie列表或點擊計數器寫到磁盤,并執行其他類似的清理活動。destory()方法與init()方法相同,只會被調用一次。
getServeltConfig()接口
getServletConfig()方法返回Servlet容器調用init()方法時傳遞給Servlet對象的ServletConfig對象,ServletConfig對象包含Servlet的初始化參數。開發者可以在Servlet的配置文件web.xml中,使用<init-param>標簽為servlet配置一些初始化參數。
getServletInfo()接口
getServletInfo()方法會返回一個String類型的字符串,包括關于Servlet的信息,如作者、版本及版權等。
四、Servlet的生命周期
我們常說的Servlet生命周期指的是servlet從創建直到銷毀的整個過程,在一個生命周期中,Servlet經歷了被加載、初始化、接收請求、響應請求以及提供服務的過程。
當用戶第一次向服務器發起請求時,服務器會解析用戶的請求,此時容器會加載Servlet,然后創建Servlet實例,再初始化servlet調用init()方法,緊接著調用服務的service()方法去處理用戶GET、POST或者其他類型的請求。當執行完Servlet中對應class文件的邏輯后,將結果返回給服務器,服務器再響應用戶請求,當服務器不再需要Servlet實例或重新載入servlet實例或重新載入servlet時會調用destory()方法,借助該方法,Servlet可以釋放掉所以在init()方法中申請的資源。
五、總結
從本質上來說JSP就是一個Servlet,因為JSP文件最終會被編譯成class文件,而這個Class文件實際上就是一個特殊的Servlet
Spring MVC框架是基于Servlet技術實現的。
代碼審計中我們可以選擇Servlet入手,也可以選擇從漏洞點反推出Http請求的入口地址。
了解Servlet知識對后續的框架審計有一定的幫助。