使用httpservletrequest可以防止盜鏈行為,什么是盜鏈行為,比如說在一個別的網站上超鏈接,指向我們的網頁中的某個數據,這樣從他的網頁上就可以直接進入到我的某個頁面,無需從我的指定路口進入:
例如在一個簡單的1.html文件中加入了我的【myservlet】web應用下的某個servlet訪問的超鏈接:
如果我的servlet中代碼僅僅為為訪問輸出數據,例如:
1
2
3
|
response.setcontenttype( "text/html;charset=utf-8" ); string data = "銀魂真是一部好動漫" ; response.getwriter().write(data); |
那么點擊這個超鏈接肯定會訪問到這個servlet:
那么我們如果不想被比人直接通過地址訪問或者超鏈接訪問怎么辦呢:
記得學習http協議中的“referer”請求頭嗎,這個請求頭是告訴服務器該請求是從哪個url發來的,那么我們就可以根據這個url來判斷是否是我們允許的請求地址來控制服務器是否將響應發送回去。
代碼如下:
1
2
3
4
5
6
7
8
9
|
string requrl = request.getheader( "referer" ); if (requrl== null || !requrl.startswith( "http://localhost:8080/myservlet/index.jsp" )){ response.sendredirect( "/myservlet/index.jsp" ); return ; } response.setcontenttype( "text/html;charset=utf-8" ); string data = "銀魂真是一部好動漫" ; response.getwriter().write(data); |
在if判斷中判斷是否為空是防止直接將該web資源以輸入url地址直接訪問,而另一個判斷是防止訪問該web資源不是從指定的地方來訪問進來。
通過該代碼,如果我們繼續在1.html頁面中點擊超鏈接,則會自動跳轉到我們設置好的index.jsp中:
而如果我們直接在瀏覽器中訪問servlet也是會跳到這個頁面的。
只有在index.jsp中點擊我們設置好的超鏈接,才能訪問到:
接下來,我們來討論的使用httpservletrequest響應對象來獲取表單數據,這是非常重要的知識點,表單提交的數據根據提交方式的不同會放置在不同位置,例如采用post方式則會將這些數據放置在http請求數據實體中,無論采用哪種方式,都是可以用響應對象的getparameter(string)等等方式獲取,這點在《servlet的學習(十)》中已經介紹。
現在,我們在需要新創建一個html頁面編寫我們的表單代碼,和一個servlet作為服務器端接收表單提交的數據,將servlet命名為servletrequest,而表單的傳送服務器和選擇http方式如下:
1
|
<form action= "/myservlet/servlet/servletrequest" method= "post" > |
先來看
1
2
|
<input type= "text" name= "user" /> <input type= "password" name= "password" /> |
這兩種常見的輸入字符情況。
當然還需要在表單中提供具有提交功能的標簽才能提交,我們選擇
1
|
<input type= "submit" value= "提交" > |
這樣的提交方式,效果如下:
在表單中這兩個都可以直接通過getparameter(string)方法獲取用戶輸入的數據,代碼如下:
1
2
|
string username = request.getparameter( "user" ); string password = request.getparameter( "password" ); |
只要我們在用戶名和密碼中輸入數據,再點擊提交,就可以將用戶名和密碼中的數據傳遞給服務器:
同時,由原來的表單的html頁面會自動跳轉到該servlet的頁面上。
對于text和password兩種表單方式的健壯性判斷:
依據:
1、如果表單中用戶名和密碼不填,那么直接提交后會是傳遞給服務器空字符串。
2、如果不是在表單,而是知道了平常表單提交后會跳轉的servlet頁面,那么直接輸入該servlet地址則是傳遞null給服務器
因此必須加入健壯性語句:
1
2
3
4
5
|
string username = request.getparameter( "user" ); if (username!= null && !username.trim().equals( "" )) { system.out.println( "user:" +username); } |
password部分代碼同理。
接下來是單選按鈕,比如性別選擇:
1
2
|
性別 <input type= "radio" name= "gender" value= "male" />男 <input type= "radio" name= "gender" value= "female" />女 |
只有<input type=”radio”>標簽中的”name”屬性一樣,才能具有單選的功能,同時”name”屬性也是在servlet中獲取用戶單選數據的重要參數,代碼:
1
|
string gender = request.getparameter( "gender" ); |
如果單選沒有選擇任何選項,則提交會返回null,所以需加入健壯性語句:
1
2
3
4
5
|
string gender = request.getparameter( "gender" ); if (gender != null ) { system.out.println(gender); } |
接下來是下拉列表,下拉列表可以是作為選擇城市,如:
1
2
3
4
5
6
7
|
城市<select name= "city" > <option value= "none" >--選擇城市--</option> <option value= "beijing" >北京</option> <option value= "shanghai" >上海</option> <option value= "hangzhou" >杭州</option> <option value= "amoy" >廈門</option> </select> |
由<select>標簽中的”name”屬性作為servlet中服務器獲取客戶端發來的下來列表數據的重要參數,代碼如下:
1
2
|
string city = request.getparameter( "city" ); system.out.println(city); |
由于下拉列表會默認選擇其第一個<option>標簽的內容,所有即使我們沒有進行任何選擇,也是會傳遞值得,這里可以無需健壯性判斷。
接下來是復選框,復選框可以是一些所學技能,或者興趣愛好,如:
1
2
3
|
<input type= "checkbox" name= "hobby" value= "sing" >唱歌 <input type= "checkbox" name= "hobby" value= "surf" >沖浪 <input type= "checkbox" name= "hobby" value= "swim" >游泳 |
由<input type=”checkbox”>標簽中的name屬性決定了這些復選框是否屬于同一個復選框組,也是同時也是作為servlet中獲取表單復選框的數據的重要參數,由于多個參數使用同一個參數名,所以必須使用getparametervalues(string)方法來獲取所有的被勾選的復選框,代碼如下(包含健壯性):
1
2
3
4
5
|
string[] hobbies = request.getparametervalues( "hobby" ); for ( int i= 0 ;hobbies!= null &&i<hobbies.length;i++) { system.out.println(hobbies[i]); } |
如果沒有勾選任何一個復選框,則不會向服務器servlet傳送任何數據。所以如果直接接收可能會發生空指針異常,必須判斷是否接收到的字符串數組有數據(hobbies!=null)。
重要:
現在,我們再重新回到<input type="text" name="user" /> 上,如果我們輸入的是中文數據,點擊提交之后會是怎樣?
在控制臺看到的結果:
結果就是出現了中文亂碼問題。這是瀏覽器在發送時通常要看當時的編碼,如:
或者:
但是!!
在servlet收到request請求對象發來的數據時,通過getparameter方法是默認查詢“iso-8859-1”碼表的,所以造成了編碼不一致!
解決方式也很簡單,只要在servlet中將獲取的request對象選擇正確的解碼方式即可,只要在代碼前添加一句:
1
|
request.setcharacterencoding( "utf-8" ); |
就可以獲取表單中正確的中文數據了:
注意,對于響應對象的setcharacterencoding方法只對http協議的post方式有效,對get方式無效。
如果我們將表單提交方式改為get,那么提交表單中有中文數據的話依然在servlet中會出現亂碼。
如果想使get方式也不會出現中文亂碼,并沒有好的捷徑方法。先要通過getparameter獲取請求數據(這時在servlet中以iso8859碼表進行解碼),然后再通過iso8859進行編碼成字節數組,最后通過創建字符串對象的方式選擇utf-8解碼表解出最開始客戶端編碼的數據。
代碼如下:
1
2
|
string usertemp = request.getparameter( "user" ); string username = new string(usertemp.getbytes( "iso8859-1" ), "utf-8" ); |
即可。
當然這種方式對post方式也是有效的。
另外一種對get方式是修改tomcat中的配置文件(這種方式只適合get方式,用post方式還是會亂碼)。通過tomcat服務器的首頁,選擇“configuration”查看配置文檔,選擇“connector”下的“http”:
在這個文檔中有一個uriencoding屬性,是指可以在server.xml文件中配置這個屬性,如果沒有這個屬性,則tomcat默認采用iso8859-1編碼:
通過在server.xml文件中的<connector>標簽中添加設置即可:
由于是在tomcat中修改server.xml文件,所以服務器需要重啟。
經過這種方式,就無需在代碼中再設置任何編碼表,所有在服務器端都會采用“uriencoding”屬性設置的碼表。但這個方式不建議使用。
同樣在“configuration”的配置文檔中的“connector”下的“http”說明文檔中,有usebodyencodingforuri這么個屬性:
當在server.xml文件中的<connector>標簽中添加設置了這個屬性,還未完成:
還必須在servlet中同時調用了響應對象的setcharacterencoding方法,就能再次使get方式不會出現亂碼:
1
2
|
request.setcharacterencoding( "utf-8" ); string username = request.getparameter( "user" ); |
同樣,這種配置server.xml文件的方式依然不建議采用。
最后說明一點,在html編程中,我們也可以使用超鏈接來提交數據,當然這樣的方式屬于http中的get方式,原理類似于在瀏覽器地址url后手動添加參數,比如如下代碼:
1
|
<a href= "/myservlet/servlet/servletrequest?user=銀魂" >用戶名為中文</a> |
跟隨的參數為中文!!
兩種解決方式:
1、在這個超鏈接上必須將這個中文進行url編碼,必須在jsp中進行編寫(在后面的篇章中會介紹如何使用);
2、或者使用上述get處理中文亂碼的第一種方式,進行雙次編碼:
1
2
|
string usertemp = request.getparameter( "user" ); string username = new string(usertemp.getbytes( "iso8859-1" ), "utf-8" ); |
也是可以的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。