在用javascript對url字元串進行編碼
中,雖然escape()、encodeuri()、encodeuricomponent()三種方法都能對一些影響url完整性的特殊字元進行過濾。
但後兩者是将字元串轉換為utf-8的方式來傳輸,解決了頁面編碼不一至導緻的亂碼問題。例如:發送頁與接受頁的編碼格式(charset)不一緻(假設
發送頁面是gb2312而接收頁面編碼是utf-8),使用escape()轉換傳輸中文字串就會出現亂碼問題。
以下是js下對url進行編/解碼的各種方法:
1、escape 方法:傳回一個可在所有計算機上讀取的編碼 string 對象。
function escape(charstring : string) : string
不會被此方法編碼的字元: @ * / +
說明:escape 方法傳回一個包含 charstring 内容的字元串值(unicode 格式)。所有空格、标點、
重音符号以及任何其他非 ascii 字元都用 %xx 編碼替換,其中 xx 等于表示該字元的十六進制數。
例如,空格傳回為“%20”。(字元值大于 255 的字元以 %uxxxx 格式存儲。)
注意:escape 方法不能用來對“統一資源辨別符”(uri) 進行編碼。對其編碼應使用 encodeuri 和encodeuricomponent 方法。
2、encodeuri 方法:傳回編碼為有效的統一資源辨別符 (uri) 的字元串。
function encodeuri(uristring : string) : string
不會被此方法編碼的字元:! @ # $ & * ( ) = : / ; ? + ‘
說明:encodeuri 方法傳回一個已編碼的 uri。如果将編碼結果傳遞給 decodeuri,則将傳回初始的字元串。encodeuri 不對下列字元進行編碼:“:”、“/”、“;”和“?”。請使用
encodeuricomponent 對這些字元進行編碼。
3、encodeuricomponent方法:傳回編碼為統一資源辨別符 (uri) 的有效元件的字元串。
function encodeuricomponent(encodeduristring : string) : string
不會被此方法編碼的字元:! * ( ) ‘
說明:encodeuricomponent 方法傳回一個已編碼的 uri。如果将編碼結果傳遞給decodeuricomponent,則将傳回初始的字元串。因為 encodeuricomponent 方法将對所有字元編碼,
請注意,如果該字元串代表一個路徑,例如 /folder1/folder2/default.html,則其中的斜杠也将被編碼,這樣,當該字元串作為請求發送到 web 伺服器時它将是無效的。如果字元串中包含多個 uri 元件,請使用 encodeuri 方法進行編碼。
4、unescape方法:從用 escape 方法編碼的 string 對象中傳回已解碼的字元串。
function unescape(charstring : string) : string
說明:unescape 方法傳回一個包含 charstring 内容的字元串值。所有以 %xx 十六進制形式編碼的
字元都用 ascii 字元集當中等效的字元代替。(以 %uxxxx 格式(unicode 字元)編碼的字元用十六
進制編碼 xxxx 的 unicode 字元代替。)
注意:unescape 方法不應用于解碼“統一資源辨別符”(uri)。請改用 decodeuri 和 decodeuricomponent 方法。
5、decodeuri 方法:傳回一個已編碼的統一資源辨別符 (uri) 的非編碼形式。
function decodeuri(uristring : string) : string
decodeuricomponent 方法:傳回統一資源辨別符 (uri) 的一個已編碼元件的非編碼形式。
function decodeuricomponent(encodeduristring : string) : string
btw:c#中對url編碼的方法。。。
編碼:server.urlencode(string)
解碼:server.urldecode(string) 前面三種用戶端編碼都可以用這個方法在背景解碼。
關于httputility.urlencode,httputility.urldecode,server.urlencode,server.urldecode
httputility.urlencode 方法:
對 url 字元串進行編碼,以便實作從 web 伺服器到用戶端的可靠的 http 傳輸。
重載清單
将位元組數組轉換為已編碼的 url 字元串,以便實作從 web 伺服器到用戶端的可靠的 http 傳輸。
[c#] public static string urlencode(byte[]);
對 url 字元串進行編碼,以便實作從 web 伺服器到用戶端的可靠的 http 傳輸。
[c#] public static string urlencode(string);
使用指定的編碼對象對 url 字元串進行編碼,以便實作從 web 伺服器到用戶端的可靠 http 傳輸。
[c#] public static string urlencode(string, encoding);
從數組中的指定位置開始一直到指定的位元組數為止,将位元組數組轉換為 url 編碼的字元串,以便實作從 web 伺服器到用戶端的可靠的 http 傳輸。
[c#] public static string urlencode(byte[], int, int);
httputility.urldecode 方法:
将已經為在 url 中傳輸而編碼的字元串轉換為解碼的字元串。
将已經為在 url 中傳輸而編碼的字元串轉換為解碼的字元串。
[c#] public static string urldecode(string);
使用指定的解碼對象将 url 編碼的位元組數組轉換為已解碼的字元串。
[c#] public static string urldecode(byte[], encoding);
使用指定的編碼對象将 url 編碼的字元串轉換為已解碼的字元串。
[c#] public static string urldecode(string, encoding);
使用指定的編碼對象,從數組中的指定位置開始到指定的位元組數為止,将 url 編碼的位元組數組轉換為已解碼的字元串。
[c#] public static string urldecode(byte[], int, int, encoding);
server是httpserverutility類的執行個體,是system.web.ui.page的屬性。
httpserverutility.urlencode 方法:
編碼字元串,以便通過 url 從 web 伺服器到用戶端進行可靠的 http 傳輸。
對字元串進行 url 編碼,并傳回已編碼的字元串。
[c#] public string urlencode(string);
url 對字元串進行編碼,并将結果輸出發送到 textwriter 輸出流。
[c#] public void urlencode(string, textwriter);
例:
string teststring = "this is a <test string>.";
stringwriter writer = new stringwriter();
server.urlencode(teststring, writer);
string encodedstring = writer.tostring();
httpserverutility.urldecode 方法:
對字元串進行解碼,該字元串為了進行 http 傳輸而進行編碼并在 url 中發送到伺服器。
對字元串進行 url 解碼并傳回已解碼的字元串。
[c#] public string urldecode(string);
對在 url 中接收的 html 字元串進行解碼,并将結果輸出發送到 textwriter 輸出流。
[c#] public void urldecode(string, textwriter);
需要注意的幾點:
1、httputility.urlencode,httputility.urldecode是靜态方法,而server.urlencode,server.urldecode是執行個體方法。
2、server是httpserverutility類的執行個體,是system.web.ui.page的屬性。
3、用httputility.urlencode編碼後的字元串和用server.urlencode進行編碼後的字元串對象不一樣:
例如:
string url="http://search.99read.com/index.aspx?book_search=all&main_str=奧迷爾";
response.write(httputility.urlencode(url));
response.write("<br>");
response.write(server.urlencode(url));
輸出結果是:
http%3a%2f%2fsearch.99read.com%2findex.aspx%3fbook_search%3dall%26main_str%3d%e5%a5%a5%e8%bf%b7%e5%b0%94
http%3a%2f%2fsearch.99read.com%2findex.aspx%3fbook_search%3dall%26main_str%3d%b0%c2%c3%d4%b6%fb
原因:server.urlencode的編碼方式是按照本地程式設定的編碼方式進行編碼的,而httputility.urlencode是預設的按照.net的utf-8格式進行編碼的。
如果改一下程式:
string url1="http://search.99read.com/index.aspx?book_search=all&main_str=奧迷爾";
response.write(httputility.urlencode(url1,system.text.encoding.getencoding("gb2312")));
response.write(server.urlencode(url1));
輸出的結果是:
http%3a%2f%2fsearch.99read.com%2findex.aspx%3fbook_search%3dall%26main_str%3d%b0%c2%c3%d4%b6%fb
4、有時候可能别的系統傳遞過來的url是用别的編碼方式編碼的。
介紹自己編寫的一個方法,可以擷取指定編碼格式的querystring。
public string getnonnullquerystring(string key,encoding encoding)
{
//引用system.collections.specialized和system.text命名空間
string stringvalue;
system.collections.specialized.namevaluecollection encodingquerystring;
//該方法是在2.0中新增的
encodingquerystring = httputility.parsequerystring(request.url.query,encoding);
//‘裡面的key就是你送出的參數的key
return encodingquerystring[key] != null ? encodingquerystring[key].trim() : "";
}
調用:
string url = getnonnullquerystring("url",encoding.utf8).trim();
在對url進行編碼時,該用哪一個?這兩都使用上有什麼差別嗎?
測試:
string file="檔案上(傳)篇.doc";
string server_urlencode=server.urlencode(file);
string server_urldecode=server.urldecode(server_urlencode);
string httputility_urlencode=system.web.httputility.urlencode(file);
string httputility_urldecode=system.web.httputility.urldecode(httputility_urlencode);
response.write("原資料:"+file);
sfun.writeline("server.urlencode:"+server_urlencode);
sfun.writeline("server.urldecode:"+server_urldecode);
sfun.writeline("httputility.urlencode:"+httputility_urlencode);
sfun.writeline("httputility.urldecode:"+httputility_urldecode);
輸出:
原資料:檔案上(傳)篇.doc
server.urlencode:%ce%c4%bc%fe%c9%cf%a3%a8%b4%ab%a3%a9%c6%aa.doc
server.urldecode:檔案上(傳)篇.doc
httputility.urlencode:%e6%96%87%e4%bb%b6%e4%b8%8a%ef%bc%88%e4%bc%a0%ef%bc%89%e7%af%87.doc
httputility.urldecode:檔案上(傳)篇.doc
差別在于:httputility.urlencode()預設是以utf8對url進行編碼,而server.urlencode()則以預設的編碼對url進行編碼。
在用 asp.net 開發頁面的時候, 我們常常通過 system.web.httputility.urlencode 和 urldecode 在頁面間通過 url 傳遞參數. 成對的使用 encode 和 decode 是沒有問題的.
但是, 我們在編寫檔案下載下傳的頁面的時候, 常常用如下方法來指定下載下傳的檔案的名稱:
response.addheader("content-disposition","attachment; filename="
+ httputility.urlencode(filename, encoding.utf8));
之是以轉換成 utf8 是為了支援中文檔案名.
這 時
候問題就來了, 因為 httputility.urlencode 在 encode 的時候, 将空格轉換成加号(‘+‘), 在 decode 的
時候将加号轉為空格, 但是浏覽器是不能了解加号為空格的, 是以如果檔案名包含了空格, 在浏覽器下載下傳得到的檔案, 空格就變成了加号.
一個解決辦法是, 在 httputility 的 urlencode 之後, 将 "+" 替換成 "%20"( 如果原來是 "+" 則被轉換成 "%2b" ) , 如:
filename = httputility.urlencode(filename, encoding.utf8);
filename = filename.replace("+", "%20");
不明白微軟為什麼要把空格轉換成加号而不是"%20". 記得 jdk 的 urlencoder 是将空格轉換成 "%20"的.
經檢查, 在 .net 2.0 也是這樣.
有
時候預設aspx是以utf-8為編碼的,你的程式預設編碼
(<globalization requestencoding="gb2312" responseencoding="gb2312"/&
gt;),問題出現了,以前沒有問題的httputility.urldecode在page.request回的值是亂碼這就是上面說的
httputility.urldecode預設以utf8對url進行編碼,這種情況下面隻需将httputility.urldecode改成
server.urlencode即可。
二.js加密解密
在做網頁時(其實是網頁木馬呵呵),最讓人煩惱的是自己辛辛苦苦寫出來的用戶端ie運作的javascript代碼常常被别人輕易的拷貝,實在讓自己的心裡有點不是滋味,要知道自己寫點東西也挺累的
^*^
以加密下面的javascript代碼為例:
<script language="javascript">
alert("《我愛一起》");
</script>
一:最簡單的加密解密
大家對于javascript函數escape()和unescape()想必是比較了解啦(很多網頁加密在用它們),分别是編碼和解碼字元串,比如例子代碼用escape()函數加密後變為如下格式:
alert%28%22%u9ed1%u5ba2%u9632%u7ebf%22%29%3b
如何?還看的懂嗎?當然其中的ascii字元"alert"并沒有被加密,如果願意我們可以寫點javascript代碼重新把它加密如下:
%61%6c%65%72%74%28%22%u9ed1%u5ba2%u9632%u7ebf%22%29%3b
呵呵!如何?這次是完全都加密了!
當然,這樣加密後的代碼是不能直接運作的,幸好還有eval(codestring)可用,這個函數的作用就是檢查javascript代碼并執行,必
選項 codestring 參數是包含有效 javascript 代碼的字元串值,加上上面的解碼unescape(),加密後的結果如下:
var code=unescape("%61%6c%65%72%74%28%22%u9ed1%u5ba2%u9632%u7ebf%22%29%3b");
eval(code)
是不是很簡單?不要高興,解密也就同樣的簡單,解密代碼都擺給别人啦(unescape())!呵呵
二:轉義字元""的妙用
大家可能對轉義字元""不太熟悉,但對于javascript提供了一些特殊字元如:n (換行)、 r (回車)、‘ (單引号)等應該是有所了解的
吧?其實""後面還可以跟八進制或十六進制的數字,如字元"a"則可以表示為:"141"或"x61"(注意是小寫字元"x"),至于雙位元組字元如漢字"
黑"則僅能用十六進制表示為"u9ed1"(注意是小寫字元"u"),其中字元"u"表示是雙位元組字元,根據這個原理例子代碼則可以表示為:
八進制轉義字元串如下:
eval("1411541451621645042u9ed1u5ba2u9632u7ebf425173")
十六進制轉義字元串如下:
eval("x61x6cx65x72x74x28x22u9ed1u5ba2u9632u7ebfx22x29x3b")
這次沒有了解碼函數,因為javascript執行時會自行轉換,同樣解碼也是很簡單如下:
alert("x61x6cx65x72x74x28x22u9ed1u5ba2u9632u7ebfx22x29x3b")
就會彈出對話框告訴你解密後的結果!
三:使用microsoft出品的腳本編碼器script encoder來進行編碼
工具的使用就不多介紹啦!我是直接使用javascript調用控件scripting.encoder完成的編碼!代碼如下:
var senc=new activexobject("scripting.encoder");
var code=‘<script language="javascript">rnalert("《我愛一起》");rn</script>‘;
var encode=senc.encodescriptfile(".htm",code,0,"");
alert(encode);
編碼後的結果如下:
<script language="jscript.encode">#@~^fgaaaa==@#@&ls dd`j黑客防線r#p@#@&fgmaaa==^#~@</script>
夠難看懂得吧?但相應的解密工具早已出來,而且連解密網頁都有!因為其解密網頁代碼過多,我就不多說拉!給大家介紹一下我獨創的解密代碼,如下:
<script language="jscript.encode">
function decode()
alert(decode.tostring());
咋樣?夠簡單吧?它是原理是:編碼後的代碼運作前ie會先對其進行解碼,如果我們先把加密的代碼放入一個自定義函數如上面的decode()中,然後對自定義函數decode調用tostring()方法,得到的将是解碼後的代碼!
如果你覺得這樣編碼得到的代碼language屬性是jscript.encode,很容易讓人識破,那麼還有一個幾乎不為人知的window對象的方法execscript(),其原形為:
window.execscript( sexpression, slanguage )
參數:
sexpression: 必選項。字元串(string)。要被執行的代碼。
slanguage : 必選項。字元串(string)。指定執行的代碼的語言。預設值為 microsoft jscript
使用時,前面的"window"可以省略不寫!
利用它我們可以很好的運作編碼後的javascript代碼,如下:
execscript("#@~^fgaaaa==@#@&ls dd`j我愛一起r#p@#@&fgmaaa==^#~@","jscript.encode")
你可以利用方法二對其中的""号内的字元串再進行編碼,使得"jscript.encode"以及編碼特征碼"#@~^"不出現,效果會更好!
四:任意添加nul空字元(十六進制00h)
一次偶然的實驗,使我發現在html網頁中任意位置添加任意個數的"空字元",ie照樣會正常顯示其中的内容,并正常執行其中的
javascript 代碼,而添加的"空字元"我們在用一般的編輯器檢視時,會顯示形如空格或黑塊,使得原碼很難看懂,如用記事本檢視則"空字元"會變
成"空格",利用這個原理加密結果如下:(其中顯示的"空格"代表"空字元")
<s c ri p t l ang u a g e =" j a v a s c r i p t ">
a l er t (" 我 愛 一 起") ;
< / sc r i p t>
如何?是不是顯得亂七八糟的?如果不知道方法的人很難想到要去掉裡面的"空字元"(00h)的!
五:無用内容混亂以及換行空格tab大法
在javascript代碼中我們可以加入大量的無用字元串或數字,以及無用代碼和注釋内容等等,使真正的有用代碼埋沒在其中,并把有用的代碼中能加入
換行、空格、tab的地方加入大量換行、空格、tab,并可以把正常的字元串用""來進行換行,這樣就會使得代碼難以看懂!如我加密後的形式如下:
"xajgxsadffgds";1234567890
625623216;var $=0;alert//@$%%&*()(&(^%^
//cctv function//
(//hhsaasajx xc
/*
asjgdsgu*/
"我愛一起"//ashjgfgf
@#%$^&%$96667r45fggbhytjty
*/
//window
)
;"#@$#%@#432hu";212351436
至少如果我看到這樣的代碼是不會有心思去分析它的,你哪?
六:自寫解密函數法
這個方法和一、二差不多,隻不過是自己寫個函數對代碼進行解密,很多vbs病毒使用這種方法對自身進行加密,來防止特征碼掃描!下面是我寫的一個簡單的加密解密函數,加密代碼如下(詳細參照檔案"加密.htm"):
function compile(code)
var c=string.fromcharcode(code.charcodeat(0)+code.length);
for(var i=1;i<code.length;i++)
alert(escape(c));
compile(‘alert("《我愛一起》");‘)
運作得到加密結果為:
o%cd%d1%d7%e6%9cj%u9ef3%ufa73%uf1d4%u14f1%u7ee1kd
相應的加密後解密的代碼如下:
function uncompile(code)
{
code=unescape(code);
var c=string.fromcharcode(code.charcodeat(0)-code.length);
return c;
eval(uncompile("o%cd%d1%d7%e6%9cj%u9ef3%ufa73%uf1d4%u14f1%u7ee1kd"));
七:錯誤的利用
利用try{}catch(e){}結構對代碼進行測試解密,雖然這個想法很好(呵呵,誇誇自己),因為實用性不大,我僅給個例子
var a=‘alert("《我愛一起》");‘;
var c="";
for(var i=0;i<a.length;i++)
alert(c);
//上面的是加密代碼,當然如果真正使用這個方法時,不會把加密寫上的
//現在變量c就是加密後的代碼
//下面的函數t()先假設初始密碼為0,解密執行,
//遇到錯誤則把密碼加1,然後接着解密執行,直到正确運作
var d=c; //儲存加密後的代碼
var b=0; //假定初始密碼為0
t();
function t()catch(e){
c="";
for(var i=0;i<d.length;i++)
b+=1;
//settimeout("t()",0);
三。實作server.urlencode和server.urldecode的js代碼
var encodeuri = function(unzipstr,iscusencode){
if(iscusencode){
var ziparray = new array();
var zipstr = "";
var lens = new array();
for(var i=0;i<unzipstr.length;i++){
var ac = unzipstr.charcodeat(i);
zipstr += ac;
lens = lens.concat(ac.tostring().length);
}
ziparray = ziparray.concat(zipstr);
ziparray = ziparray.concat(lens.join("o"));
return ziparray.join("n");
}else{
//return encodeuri(unzipstr);
var zipstr="";
var strspecial="!\"#$%&‘()*+,/:;<=>?[]^`{|}~%";
var tt= "";
for(var i=0;i<unzipstr.length;i++){
var chr = unzipstr.charat(i);
var c=stringtoascii(chr);
tt += chr+":"+c+"n";
if(parseint("0x"+c) > 0x7f){
zipstr+=encodeuri(unzipstr.substr(i,1));
}else{
if(chr==" ")
zipstr+="+";
else if(strspecial.indexof(chr)!=-1)
zipstr+="%"+c.tostring(16);
else
zipstr+=chr;
}
}
return zipstr;
}
var decodeuri = function(zipstr,iscusencode){
var ziparray = zipstr.split("n");
var zipsrcstr = ziparray[0];
var ziplens;
if(ziparray[1]){
ziplens = ziparray[1].split("o");
}else{
ziplens.length = 0;
}
var uzipstr = "";
for(var j=0;j<ziplens.length;j++){
var charlen = parseint(ziplens[j]);
uzipstr+= string.fromcharcode(zipsrcstr.substr(0,charlen));
zipsrcstr = zipsrcstr.slice(charlen,zipsrcstr.length);
}
return uzipstr;
//return decodeuri(zipstr);
var uzipstr="";
for(var i=0;i<zipstr.length;i++){
var chr = zipstr.charat(i);
if(chr == "+"){
uzipstr+=" ";
}else if(chr=="%"){
var asc = zipstr.substring(i+1,i+3);
if(parseint("0x"+asc)>0x7f){
uzipstr+=decodeuri("%"+asc.tostring()+zipstr.substring(i+3,i+9).tostring()); ;
i+=8;
}else{
uzipstr+=asciitostring(parseint("0x"+asc));
i+=2;
}
uzipstr+= chr;
var stringtoascii = function(str){
return str.charcodeat(0).tostring(16);
var asciitostring = function(asccode){
return string.fromcharcode(asccode);