㈠ 文件上傳漏洞攻擊方法有什麼
文件上傳漏洞是什麼?怎樣防禦文件上傳漏洞攻擊?文件上傳漏洞是web安全中經常利用到的一種漏洞形式。這種類型的攻擊從大的類型上來說,是攻擊 數據與代碼分離原則 的一種攻擊。
一些web應用程序中允許上傳圖片,文本或者其他資源到指定的位置,文件上傳漏洞就是利用這些可以上傳的地方將惡意代碼植入到伺服器中,再通過url去訪問以執行代碼
造成文件上傳漏洞的原因是
對於上傳文件的後綴名(擴展名)沒有做較為嚴格的限制
對於上傳文件的MIMETYPE 沒有做檢查
許可權上沒有對於上傳的文件的文件許可權,(尤其是對於shebang類型的文件)
對於web server對於上傳文件或者指定目錄的行為沒有做限制
下面就閑話一些文件上傳漏洞的防禦方式和攻擊者的繞過方式
1.前端限制
function check(){
var filename=document.getElementById("file");
var str=filename.value.split(".");
var ext=str[str.length-1];
if(ext=='jpg'||ext=='png'||ext=='jpeg'||ext=='gif'){
return true;
}else{
alert("這不是圖片!")
return false;
}
return false;
}
在表單中使用onsumbit=check()調用js函數來檢查上傳文件的擴展名。這種限制實際上沒有任何用處,任何攻擊者都可以輕而易舉的破解。只能用於對於用戶完全信任的情況下,很難稱之為一種安全措施只能稱之是一種防止用戶誤操作上傳的措施,
反制:
隨便的編輯一下頁面/用burpsuite/寫個小腳本就可以突破之,無須多言
2.檢查擴展名
顧名思義,就是在文件被上傳到服務端的時候,對於文件名的擴展名進行檢查,如果不合法,則拒絕這次上傳
在這里,還有一點是值得一提的,在檢查擴展名是否合法的時候,有兩種策略
黑名單策略,文件擴展名在黑名單中的為不合法,示例代碼
$postfix = end(explode('.','$_POST['filename']);
if($postfix=='php'||$postfix=='asp'||$postfix=='sh'){
echo "invalid file type";
return;
}
白名單策略,文件擴展名不在白名單中的均為不合法
$postfix = end(explode('.','$_POST['filename']);
if($postfix=='jpg'||$postfix=='png'||$postfix=='gif'){
//save the file and do something next
} else {
echo "invalid file type";
return;
}
白名單策略是更加安全的,通過限制上傳類型為只有我們接受的類型,可以較好的保證安全,因為黑名單我們可以使用各種方法來進行注入和突破
反制
在一些 webserver 中,存在解析漏洞
1.老版本的IIS中的目錄解析漏洞,如果網站目錄中有一個 /.asp/目錄,那麼此目錄下面的一切內容都會被當作asp腳本來解析
2.老闆本的IIS中的分號漏洞:IIS在解析文件名的時候可能將分號後面的內容丟棄,那麼我們可以在上傳的時候給後面加入分號內容來避免黑名單過濾,如 a.asp;jpg
3.舊版Windows Server中存在空格和dot漏洞類似於 a.php. 和 a.php[空格] 這樣的文件名存儲後會被windows去掉點和空格,從而使得加上這兩個東西可以突破過濾,成功上傳,並且被當作php代碼來執行
4.nginx空位元組漏洞 xxx.jpg%00.php 這樣的文件名會被解析為php代碼運行
5.apache的解析漏洞,上傳如a.php.rar a.php.gif 類型的文件名,可以避免對於php文件的過濾機制,但是由於apache在解析文件名的時候是從右向左讀,如果遇到不能識別的擴展名則跳過,rar等擴展名是apache不能識別的,因此就會直接將類型識別為php,從而達到了注入php代碼的目的
3.檢查HTTP Header中的Content-Type
HTTP協議規定了上傳資源的時候在Header中加上一項文件的MIMETYPE,來識別文件類型,這個動作是由瀏覽器完成的,服務端可以檢查此類型不過這仍然是不安全的,因為HTTP header可以被發出者或者中間人任意的修改,不過加上一層防護也是可以有一定效果的
反制
使用各種各樣的工具(如burpsuite)強行篡改Header就可以,太容易將header中的
Content-Type: application/php
或者其他類型
改為
Content-Type: image/jpg
Content-Type: image/png
Content-Type: text/plain
等這些web程序允許的淚洗改附上常用的MIMETYPE表
text/plain(純文本)
text/html(HTML文檔)
text/javascript(js代碼)
application/xhtml+xml(XHTML文檔)
image/gif(GIF圖像)
image/jpeg(JPEG圖像)
image/png(PNG圖像)
video/mpeg(MPEG動畫)
application/octet-stream(二進制數據)
application/pdf(PDF文檔)
application/(編程語言) 該種語言的代碼
application/msword(Microsoft Word文件)
message/rfc822(RFC 822形式)
multipart/alternative(HTML郵件的HTML形式和純文本形式,相同內容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交的表單)
multipart/form-data(POST提交時伴隨文件上傳的表單)
4.分析文件頭內容來檢查文件類型
與方法2不同,還有一種檢查類型的方式是使用對於文件內容的驗證機制,這種方法利用的是每一個特定類型的文件都會有不太一樣的開頭或者標志位。可以通過比如php的exif_imagetype()函數,一個通過這種方法來過濾的示例代碼如下:
if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {
echo "File is not an image";
return;
}
也可以自己編寫函數來進行識別,圖片文件通常有稱作幻數的頭位元組,我們來看一下幾種圖片文件的幻數:
(注意!下面是二進制而不是文本格式的數據)
JPG
FF D8 FF E0 00 10 4A 46 49 46
GIF
47 49 46 38 39 61
(相當於文本的GIF89a)
PNG
89 50 4E 47
通過檢查頭幾位位元組,可以分辨是否是圖片文件
如果是其他類型的二進制文件,也有響應的頭位元組,如下表
反制
給上傳腳本加上相應的幻數頭位元組就可以,php引擎會將
(一般不限制圖片文件格式的時候使用GIF的頭比較方便,因為全都是文本可列印字元。)
GIF89a
do_something();
?>
如果是其他類型的二進制文件,也有響應的頭位元組,如下表
格式
文件頭
TIFF (tif)
49492A00
Windows Bitmap (bmp)
424D
CAD (dwg)
41433130
Adobe Photoshop (psd)
38425053
Rich Text Format (rtf)
7B5C727466
MS Word/Excel (xls.or.doc)
D0CF11E0
MS Access (mdb)
5374616E64617264204A
ZIP Archive (zip),
504B0304
RAR Archive (rar),
7221
Wave (wav),
57415645
AVI (avi),
41564920
Real MEdia (rm),
2E524D46
MPEG (mpg),
000001BA
MPEG (mpg),
000001B3
Quicktime (mov),
6D6F6F76
Adobe Acrobat (pdf),
255044462D312E
Windows Media (asf),
3026B2758E66CF11
MIDI (mid),
4D546864
5.限制Web Server對於特定類型文件的行為
導致文件上傳漏洞的根本原因在於服務把用戶上傳的本應是數據的內容當作了代碼,一般來說,用戶上傳的內容都會被存儲到特定的一個文件夾下,比如我們很多人習慣於放在 ./upload/ 下面要防止數據被當作代碼執行,我們可以限制web server對於特定文件夾的行為。
大多數服務端軟體都可以支持用戶對於特定類型文件的行為的自定義,以Apache為例:
在默認情況下,對與 .php文件Apache會當作代碼來執行,對於 html,css,js文件,則會直接由HTTP Response交給客戶端程序對於一些資源文件,比如txt,doc,rar等等,則也會以文件下載的方式傳送的客戶端。我們希望用戶上傳的東西僅僅當作資源和數據而不能當作代碼
因此可以使用伺服器程序的介面來進行限制
以Apache為例,我們可以利用 .htaccess 文件機制來對web server行為進行限制
在這里插一句,如果不是專門的文件下載目錄,請務必關掉文件夾瀏覽的許可權,以防止嗅探和可能的越權,也是使用.htaccess文件,在其中加上一句
Options All -Indexes
即可。
禁止腳本執行有多種方式可以實現,而且分別有不同的效果,我們分別來看一下
1.指定特定擴展名的文件的處理方式,原理是指定Response的Content-Type可以加上如下幾行
AddType text/plain .pl .py .php
這種情況下,以上幾種腳本文件會被當作純文本來顯示出來,你也可以換成其他的Content-Type
2.如果要完全禁止特定擴展名的文件被訪問,用下面的幾行
Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi識別
在這種情況下,以上幾種類型的文件被訪問的時候,會返回403 Forbidden的錯誤
3.也可以強制web伺服器對於特定文件類型的處理,與第一條不同的是, 下面的方法直接強行讓apache將文件識別為你指定的類型,而第一種是讓瀏覽器
ForceType text/plain
看代碼就可以很明白的知道,符合上面正則的全部被認為是純文本,也可以繼續往裡面加入其他類型。
4.只允許訪問特定類型的文件
order deny,allow
deny from all
在一個上傳圖片的文件夾下面,就可以加上這段代碼,使得該文件夾裡面只有圖片擴展名的文件才可以被訪問,其他類型都是拒絕訪問。
這又是一個白名單的處理方案
永遠記得,白名單是最有保障的安全措施
可以通過 move_uploaded_file 函數把自己寫的.htaccess 文件上傳,覆蓋掉伺服器上的文件,來定義文件類型和執行許可權如果做到了這一點,將獲得相當大的許可權。
㈡ 分號在java中的作用,什麼時候用,什麼時候不能用.
1、分號標志著Java一句完整代碼的結束。
2、一般也用來拼接字元串,分割字元串的分隔符。
3、一句完整sql的結束(資料庫中),Java代碼里的sql是不加分號的
暫時想到這么多。。。
㈢ java 方法 出現錯誤(提示說需要分號)可我看不出來
你這段代碼直接拷貝出來執行沒有出現你所說的問題,但是有別的問題,i2在if(i2==10)的判斷的時候因為i2沒有初始化所以報了個錯,如果當if(i2==10)不成立的時候這個函數沒有返回值,給你改了一下,你看看這樣行不行
booleanbNewLine(Stringss){
intilen=ss.length();
inti1,i2;
i1=ss.codePointAt(ilen-2);
i2=ss.codePointAt(ilen-1);
if(i1==13){
System.out.println("包含回車。");
if(i2==10){
System.out.println("包含換行。");
returntrue;
}
}else{
System.out.println("不包含回車換行。");
}
returnfalse;
}
㈣ java怎麼把字元串最後一個去掉,比如說29.0」,我要把最後那個分號」去掉,怎麼去
給你個例子:
publicclasstest{
publicstaticvoidmain(String[]args){
StringS="29.0」";
System.out.println(S.substring(0,S.length()-1));
}
}
㈤ 如何安全檢測Java Web應用網站漏洞
如何安全檢測Java Web應用網站漏洞.txt32因為愛心,流浪的人們才能重返家園;因為愛心,疲憊的靈魂才能活力如初。渴望愛心,如同星光渴望彼此輝映;渴望愛心,如同世紀之歌渴望永遠被唱下去。web開發應用程序(網站),是目前應用最廣泛的程序。但是開發者的水平參差不齊,導致了各種各樣web漏洞的出現。本文站在分層架構的角度,分析一下如何在java web程序中找到可能出現的種種漏洞。 本文討論的只是web程序上的漏洞,和其它漏洞,是相對獨立的。這句話看似廢話,實際上卻說明了時常被忽略的因素,即:「很多人認為只要我開發web程序沒有漏洞,web伺服器就安全了」,事實上,並非如此。一個合格的web程序開發人員,應該時刻清楚自己開發的程序會在什麼環境中被使用,以及一旦自己的程序產生某種漏洞,最終會導致什麼後果。簡單的說,web程序被安裝在一台或多台(分布式)web伺服器上,一旦安裝成功,就等於在為廣大用戶提供服務的同時,給入侵者打開了一條或N條新的思路。如果伺服器管理員剛好對安全配置不了解(事實上,國內這種管理員居多),那麼只好由我們的程序來守好最後的關卡最後一道防線。 看了本文題目,一定有一部分人會認為,「不就是講JSP漏洞么,用得著披著這么厚的包裝么?」,為了回答這個疑問,我們先看看JSP和ASP的開發有什麼不同吧。在ASP時代(ASP,PHP等語言),開發一套系統往往比修改別人已經寫好的系統痛苦的多,因為它們把所有的代碼(包括鏈接資料庫的代碼、執行SQL語句的代碼、控制頁面顯示的代碼)統統都放在<%......%>中,我們時常會看到如下代碼塊: -----------代碼來自某ASP SHELL----------- Function GetFileSize(size) Dim FileSize FileSize=size / 1024 FileSize=FormatNumber(FileSize,2) If FileSize < 1024 and FileSize > 1 then GetFileSize="<font color=red>"& FileSize & "</font>KB" ElseIf FileSize >1024 then GetFileSize="<font color=red>"& FormatNumber(FileSize / 1024,2) & "</font>MB" Else GetFileSize="<font color=red>"& Size & "</font>Bytes" End If End Function ---------------------------------------- 如果客戶的需求變了,要求頁面不能使用「<font color=red>」等標簽,全部應用「CSS」顯示。掛了,把程序員召喚出來,一個一個的改吧。。。注意,這里強調下,特指「召喚程序員」才能改,如果是學美工的,只會HTML、JS、CSS,完了,這活還幹不成。而這些只是簡單的頁面修改,如果客戶今天說,MYSQL伺服器承擔不了這個數據量,要掛Oracle,可憐的程序員就要在一片一片的代碼海洋里尋找執行SQL語句的代碼,而每一個文件都可能存放著SQL語句,意味著每一個文件都可能在受SQL注入的威脅。
而JSP採用MVC模式分層架構進行開發,就可以把所有的文件分開,根據其用途,分別放在不同的文件夾下(分層),每個文件夾下的文件只負責自己的事情。例如數據訪問層的代碼就放在數據訪問層的文件夾下,業務邏輯層的代碼也都放在自己的文件夾下,當顯示層(這一層是為了把最終的運算結果顯示給用戶看)的需求發生變化,就像前面的客戶需求,我們只要修改這一層的文件就是了,其他層的代碼根本不需要動,而修改者也不需要懂得其它層的代碼。 代碼分層了,意味著漏洞也在跟著分層,我們尋找JSP漏洞的思路也要跟著分層,才能與時俱進。 下面在講述尋找漏洞的過程中,本文就拿一個簡單的分層架構例子來做樣板。樣板程序的名稱為「XX文章系統」,系統使用了STRUTS框架,和安全有關的層分為: 「DB層」,這一層存放了鏈接資料庫的字元串,以及JdbcTemplate類,直接訪問資料庫。因為在java中,執行SQL語句的函數按照返回值可以分為三類,所以在這一層定義了JDBC模版類(JdbcTemplate),每一次使用操作資料庫時都要執行這一層的三個方法其中一個。 「DAO層(Data Access Object數據訪問對象層)」,從安全形度上看,這一層存放了SQL語句(並不執行SQL語句,語句傳給DB層執行)。這一層調用「DB層」訪問資料庫,它只知道「DB層」的存在,不知道資料庫的存在。 「SERVICE層」,業務邏輯層,因為一個業務的實現,並不是一次資料庫訪問就可以完成的,所以這一層通過N次調用「DAO層的方法」實現業務邏輯,它只知道「DAO層」的存在,不知道「DB層」和資料庫的存在。 「ACTION層」,調用業務邏輯層,根據返回的結果,控制JSP頁面顯示。它只知道業務層的存在。這一層是入侵者的攻擊平台。 「Form層」,把用戶POST提交的信息封裝成Form對象,經過驗證後提交給ACTION層處理。 「JSP層」(顯示層),這一層是最終顯示給用戶看的頁面,同時也是入侵者的攻擊平台。 用戶通過訪問ACTION層,自動會發生:「ACTION調用SERVICE,SERVICE調用DAO,DAO調用DB,DB執行SQL語句返回結果給DAO,DAO返回給SERVICE,SERVICE返回給ACTION,ACTION把數據顯示到JSP里返回給用戶」。 有了樣板,我們來分析這套程序中可能出現的各種web漏洞。 1、SQL注入漏洞 從SQL注入漏洞說起吧,在web漏洞里,SQL注入是最容易被利用而又最具有危害性的。怎麼快速的找到呢?先分析流程,就拿用戶查看文章這個流程為例:用戶訪問一個
action,告訴它用戶想看ID為7的文章,這個action就會繼續完成前面所說的流程。 如果是ASP程序,這就是最容易產生問題的時候,ASP是弱類型,接到參數後不需要轉換類型,就和SQL語句連加起來。但是JSP就不一樣,JSP是強類型的語言,接受有害的參數後:對於GET請求(直接在地址欄訪問頁面),如果這里要的是int型,即使不懂安全的程序員,也會把它(文章的ID)立刻轉換成int,因為這里轉換後在後面的處理中會更容易操作,而這時程序就出錯了;對於POST請求,如果這里要的是int型,程序會在把它封裝成Form對象時,因為自動要進行類型轉化,同樣發生錯誤,這兩種錯誤發生後,根本不會訪問後面的流程就跳出了,或許這就是JSP天生的安全性。所以,通常提交的變數是int時,不會發生問題,問題會出現在string參數這里,如果要查看某用戶的信息,程序可能會讓你提交如下參數:showuser.do? username=kxlzx。問題來了,因為這里是string類型,所以不懂安全的程序員頂多會判斷一下是不是空,就連加成為SQL語句。有漏洞的程序大概會寫成這個樣子: ACTION的代碼: showuser.do String username = null; username = request.getParameter("username"); Service service = new Service(); service.findByUsername(username); 得到參數後調用service,service層直接交給了Dao層,的代碼: public Object findByUsername(String username) { JdbcTemplate jt=new JdbcTemplate(); String sql = "select * from Users where username=』"+username"』"; List list = jt.query(sql); ................... } 調用了DB層的JdbcTemplate,把SQL語句拼好後,傳給了JdbcTemplate去執行。不用再看這里的JdbcTemplate,就可以知道裡面的代碼使用了Statement的executequery()方法執行,導致了SQL注入。 分析了這么半天,有讀者會問:「難道我要費這么大的力氣才能找到漏洞么?」。的確,通常在ASP程序里找注入時的思路就是這樣子,但是我們現在是在使用了開發模式分層架構的JSP程序里,應該按照分層架構的思維去找漏洞。在回答這個問題之前,我們還得繞個彎子,看看怎麼在這里預防SQL注入(java始終都是這么優美,它不會直接告訴你答案,而是一層一層的讓你撥開雲霧)。 剛才分析流程,是從正向分析的,從用戶輸入到產生漏洞,我們在防禦的時候,不妨倒過來看看,從DB層入手。JdbcTemplate調用執行SQL語句,可以有兩個類供我們選擇,一個是Statement,另一個就是預處理的Statement,兩者有著效率上和安全上的顯著差別。在效率上,只要資料庫支持預處理技術(sqlserver,mysql,oracle等都支持,只有少數access等不支持),就會在大量執行SQL語句時增加速度;在安全上,使用預處理,會把接受的參數也經過預處理,從而不會作為SQL語句的一部分執行,而是僅僅作為SQL語句中的參數部分
內容被執行。一旦DB層使用了預處理,DAO層的SQL語句也會發生變化,成為這個樣子: public Object findByUsername(String username) { JdbcTemplate jt=new JdbcTemplate(); String sql = "select * from Users where username=?"; List list = jt.query(sql,new Object[1]{username}); ................... } 這樣,SQL注入就和我們的程序幾乎無關了,注意我說的是幾乎,而不是全部。知道了怎麼防禦,於是一切在這里變的簡單極了,我們應該直接去DB層找到JdbcTemplate,看看代碼,一旦使用了Statement,很好,這個系統十有八九有漏洞,下面要做的是使用Editplus搜索「request.getParameter」。沒有使用預處理的系統,可能會在action層進行防禦,對參數過濾,但總有防禦不到的時候,因為戰線拉的太長了,每一個action里都可能接受參數並存在漏洞。 還有一種情況,系統一部分使用了預處理,一部分沒有,這樣的情況可能是因為項目趕的比較倉促,人員沒有經過正規培訓,最後艱難的整合到了一起。這種情況也好辦,直接在DAO層搜索("』)或(』"),這些符號用於和字元串變數連加,拼SQL語句,肯定是這些語句之後的代碼使用了Statement。然後再往上層找,看看哪個action調用了這個有問題的類,也可能發生SQL注入。 即使系統使用了預處理,別忘了,程序給客戶使用後,客戶有權利去擴展的。程序拿到客戶那裡,客戶有了新的需求,而這個需求又不大,很可能不願意花錢重新僱人來實現擴展功能,在這個時候也可能出現問題,客戶使用自己的程序員擴展AJAX功能,這個程序員因為怕出問題,不敢動源程序,就在web.xml里加了一個servlet,這個servlet直接去調用conn。可怕的事情發生了。所以,我們的搜索漏洞規則中又加上了一條,在非層的文件中,搜索「select,update,delete」等字元串。 2、暴露程序信息漏洞 這個漏洞是怎麼來的呢?我們需要從異常說起。有經驗的入侵者,可以從JSP程序的異常中獲取很多信息,比如程序的部分架構、程序的物理路徑、SQL注入爆出來的信息等,這個漏洞很容易防禦,卻很難快速定位漏洞文件。出現這樣漏洞的時候,通常是我們在寫代碼的時候,少了一些可能性的考慮而導致的。這樣的問題都是經驗造成的,而尋找漏洞也要通過經驗加運氣(要有仙緣。。。),我個人技術有限,就不多說了。防禦的方法就是在程序中加上「Exception層」,自定義異常,把系統產生的異常統統包裝起來,不要放過任何一個可能產生異常的地方。像騰訊的異常就包裝的很好「對不起,今天的注冊人數已經達到十萬,請您明天再來。。。」,廢話,日注冊量都十萬,還讓不讓人活啦,鐵定是程序發生了異常,不敢讓各位大大們看到真實的面孔。
㈥ java中 如何用split過濾掉String中[]括弧
java 中 split 的意思就是依據標記分解出 S熱ing數組,而不是過濾;
你要搞清楚用法和目的,你可以使用 .replace("[",""); .replace("}","");
也可以寫regex,匹配「[]」.你看是不是你要的答案吧。
對於你的追問:可以的.split("\[\]");可以返回數組。或者你先 替換[] 成 ;在依據分號split,不就OK了?對吧,思路很多的,你也可以開闊一下思路,
㈦ Java中如何解決sql 注入漏洞
1、對傳遞過來的參數值段做過濾處理 包含sql操作關鍵字的幹掉!當然這個要符合你回的業務需求
2、不要答對sql語句做拼接處理 可以用類似 jdbc中的preparestatement動態sql技術 生成sql
3、對傳遞進來的參數值做字元串轉義 'sql do some' 讓資料庫把這段當成一段字元串處理 而不進行操作編譯
㈧ java遠程代碼執行漏洞
struts2會將http的每個參數名解析為ongl語句執行(可理解為Java代碼)。 ongl表達式通過#來訪問struts的對象,struts框架通過過濾#字元防止安全問題,然而通過unicode編碼(\u0023)或8進制(\43)即繞過了安全限制。
㈨ Java 開發中用到的幾種過濾器
在Java中有時會遇見亂碼的情況,這里提供了幾種轉換方法(一)Java中的編碼轉換 (二)可以在web.xml文件中配置的自己寫的過濾器 第一種方法最簡單也最方便,但是只能用在少量的地方或是偶爾一兩次轉碼,如果大面積使用就不方便了,也大大增加了編碼量,如果你的項目里沒有用Spring的框架開發,用web.xml配置自定義過濾器可以一勞永逸的解決 1.首先要編寫自己的過濾器類(實現了javax.servlet.Filter): package fck.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class CodeFilter implements Filter { public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException { // TODO Auto-generated method stub request.setCharacterEncoding("utf-8"); filter.doFilter(request, response); } public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } } 2.在web.xml文件中編寫過濾器配置: CodeFilter fck.filter.CodeFilter CodeFilter /* 之後不用再做什麼代碼的改變,過濾器就將所有的訪問都轉碼了 (三)使瀏覽器不緩存頁面的過濾器 import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** *//** * 用於的使 Browser 不緩存頁面的過濾器 */ public class ForceNoCacheFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException{ ((HttpServletResponse) response).setHeader("Cache-Control","no-cache"); ((HttpServletResponse) response).setHeader("Pragma","no-cache"); ((HttpServletResponse) response).setDateHeader ("Expires", -1); filterChain.doFilter(request, response); } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } } (四)檢測用戶是否登陸的過濾器 import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.List; import java.util.ArrayList; import java.util.StringTokenizer; import java.io.IOException; /** */ /** * 用於檢測用戶是否登陸的過濾器,如果未登錄,則重定向到指的登錄頁面 * 配置參數 * checkSessionKey 需檢查的在 Session 中保存的關鍵字 * redirectURL 如果用戶未登錄,則重定向到指定的頁面,URL不包括 ContextPath * notCheckURLList 不做檢查的URL列表,以分號分開,並且 URL 中不包括 ContextPath */ public class T implements Filter { protected FilterConfig filterConfig = null; private String redirectURL = null; private List notCheckURLList = new ArrayList(); private String sessionKey = null; public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; HttpSession session = request.getSession(); if (sessionKey == null) { filterChain.doFilter(request, response); return; } if ((!(request)) && session.getAttribute(sessionKey) == null) { response.sendRedirect(request.getContextPath() + redirectURL); return; } filterChain.doFilter(servletRequest, servletResponse); } public void destroy() { notCheckURLList.clear(); } private boolean (HttpServletRequest request) { String uri = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo()); return notCheckURLList.contains(uri); } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; redirectURL = filterConfig.getInitParameter("redirectURL"); sessionKey = filterConfig.getInitParameter("checkSessionKey"); String notCheckURLListStr = filterConfig.getInitParameter("notCheckURLList"); if (notCheckURLListStr != null) { StringTokenizer st = new StringTokenizer(notCheckURLListStr, ";"); notCheckURLList.clear(); while (st.hasMoreTokens()) { notCheckURLList.add(st.nextToken()); } } } } (五)資源保護過濾器 import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Iterator; import java.util.Set; import java.util.HashSet; // import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** */ /** * This Filter class handle the security of the application. * * It should be configured inside the web.xml. * * @author Derek Y. Shen */ public class SecurityFilter implements Filter { // the login page uri private static final String LOGIN_PAGE_URI = "login.jsf"; // the logger object private Log logger = LogFactory.getLog(this.getClass()); // a set of restricted resources private Set restrictedResources; /** */ /** * Initializes the Filter. */ public void init(FilterConfig filterConfig) throws ServletException { this.restrictedResources = new HashSet(); this.restrictedResources.add("/createProct.jsf"); this.restrictedResources.add("/editProct.jsf"); this.restrictedResources.add("/proctList.jsf"); } /** */ /** * Standard doFilter object. */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { this.logger.debug("doFilter"); String contextPath = ((HttpServletRequest) req).getContextPath(); String requestUri = ((HttpServletRequest) req).getRequestURI(); this.logger.debug("contextPath = " + contextPath); this.logger.debug("requestUri = " + requestUri); if (this.contains(requestUri, contextPath) && !this.authorize((HttpServletRequest) req)) { this.logger.debug("authorization failed"); ((HttpServletRequest) req).getRequestDispatcher(LOGIN_PAGE_URI) .forward(req, res); } else { this.logger.debug("authorization succeeded"); chain.doFilter(req, res); } } public void destroy() { } private boolean contains(String value, String contextPath) { Iterator ite = this.restrictedResources.iterator(); while (ite.hasNext()) { String restrictedResource = (String) ite.next(); if ((contextPath + restrictedResource).equalsIgnoreCase(value)) { return true; } } return false; } private boolean authorize(HttpServletRequest req) { // 處理用戶登錄 /**//* * UserBean user = * (UserBean)req.getSession().getAttribute(BeanNames.USER_BEAN); * * if (user != null && user.getLoggedIn()) { //user logged in return * true; } else { return false; } */ } } (六) 利用Filter限制用戶瀏覽許可權 import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class T implements Filter { public void destroy() { } public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain arg2) throws IOException, ServletException { // 獲取uri地址 HttpServletRequest request = (HttpServletRequest) sreq; String uri = request.getRequestURI(); String ctx = request.getContextPath(); uri = uri.substring(ctx.length()); // 判斷admin級別網頁的瀏覽許可權 if (uri.startsWith("/admin")) { if (request.getSession().getAttribute("admin") == null) { request.setAttribute("message", "您沒有這個許可權"); request.getRequestDispatcher("/login.jsp").forward(sreq, sres); return; } } // 判斷manage級別網頁的瀏覽許可權 if (uri.startsWith("/manage")) { // 這里省去 } } // 下面還可以添加其他的用戶許可權,省去。