【前端安全】JavaScript防http劫持與XSS
作為前端,一直以來都知道HTTP劫持
與XSS跨站指令碼
(Cross-site scripting)、CSRF跨站請求偽造
(Cross-site request forgery)。但是一直都沒有深入研究過,前些日子同事的分享會偶然提及,我也對這一塊很感興趣,便深入研究了一番。
最近用 JavaScript 寫了一個元件,可以在前端層面防禦部分 HTTP 劫持與 XSS。
當然,防禦這些劫持最好的方法還是從後端入手,前端能做的實在太少。而且由於原始碼的暴露,攻擊者很容易繞過我們的防禦手段。但是這不代表我們去了解這塊的相關知識是沒意義的,本文的許多方法,用在其他方面也是大有作用。
已上傳到 Github –
接下來進入正文。
HTTP劫持、DNS劫持與XSS
先簡單講講什麼是 HTTP 劫持與 DNS 劫持。
HTTP劫持
什麼是HTTP劫持呢,大多數情況是運營商HTTP劫持,當我們使用HTTP請求請求一個網站頁面的時候,網路運營商會在正常的資料流中插入精心設計的網路資料報文,讓客戶端(通常是瀏覽器)展示“錯誤”的資料,通常是一些彈窗,宣傳性廣告或者直接顯示某網站的內容,大家應該都有遇到過。
DNS劫持
DNS劫持就是通過劫持了DNS伺服器,通過某些手段取得某域名的解析記錄控制權,進而修改此域名的解析結果,導致對該域名的訪問由原IP地址轉入到修改後的指定IP,其結果就是對特定的網址不能訪問或訪問的是假網址,從而實現竊取資料或者破壞原有正常服務的目的。
DNS 劫持就更過分了,簡單說就是我們請求的是 http://www.a.com/index.html ,直接被重定向了 http://www.b.com/index.html ,本文不會過多討論這種情況。
XSS跨站指令碼
XSS指的是攻擊者漏洞,向 Web 頁面中注入惡意程式碼,當用戶瀏覽該頁之時,注入的程式碼會被執行,從而達到攻擊的特殊目的。
關於這些攻擊如何生成,攻擊者如何注入惡意程式碼到頁面中本文不做討論,只要知道如 HTTP 劫持 和 XSS 最終都是惡意程式碼在客戶端,通常也就是使用者瀏覽器端執行,本文將討論的就是假設注入已經存在,如何利用 Javascript 進行行之有效的前端防護。
頁面被嵌入 iframe 中,重定向 iframe
先來說說我們的頁面被嵌入了 iframe 的情況。也就是,網路運營商為了儘可能地減少植入廣告對原有網站頁面的影響,通常會通過把原有網站頁面放置到一個和原頁面相同大小的 iframe 裡面去,那麼就可以通過這個 iframe 來隔離廣告程式碼對原有頁面的影響。
這種情況還比較好處理,我們只需要知道我們的頁面是否被巢狀在 iframe 中,如果是,則重定向外層頁面到我們的正常頁面即可。
那麼有沒有方法知道我們的頁面當前存在於 iframe 中呢?有的,就是 window.self
與 window.top
。
window.self
返回一個指向當前 window 物件的引用。
window.top
返回視窗體系中的最頂層視窗的引用。
對於非同源的域名,iframe 子頁面無法通過 parent.location 或者 top.location 拿到具體的頁面地址,但是可以寫入 top.location ,也就是可以控制父頁面的跳轉。
兩個屬性分別可以又簡寫為 self
與 top
,所以當發現我們的頁面被巢狀在 iframe 時,可以重定向父級頁面:
1 2 3 4 5 6 |
if
(self != top) {
// 我們的正常頁面
var
url = location.href;
// 父級頁面重定向
top.location = url;
}
|
使用白名單放行正常 iframe 巢狀
當然很多時候,也許運營需要,我們的頁面會被以各種方式推廣,也有可能是正常業務需要被巢狀在 iframe 中,這個時候我們需要一個白名單或者黑名單,當我們的頁面被巢狀在 iframe 中且父級頁面域名存在白名單中,則不做重定向操作。
上面也說了,使用 top.location.href 是沒辦法拿到父級頁面的 URL 的,這時候,需要使用document.referrer
。
通過 document.referrer 可以拿到跨域 iframe 父頁面的URL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// 建立白名單
var
whiteList = [
'www.aaa.com' ,
'res.bbb.com'
];
if
(self != top) {
var
// 使用 document.referrer 可以拿到跨域 iframe 父頁面的 URL
parentUrl = document.referrer,
length = whiteList.length,
i = 0;
for (; i<length; i++){
// 建立白名單正則
var
reg = new
RegExp(whiteList[i], 'i' );
// 存在白名單中,放行
if (reg.test(parentUrl)){
return ;
}
}
// 我們的正常頁面
var
url = location.href;
// 父級頁面重定向
top.location = url;
}
|
更改 URL 引數繞過運營商標記
這樣就完了嗎?沒有,我們雖然重定向了父頁面,但是在重定向的過程中,既然第一次可以巢狀,那麼這一次重定向的過程中頁面也許又被 iframe 嵌套了,真尼瑪蛋疼。
當然運營商這種劫持通常也是有跡可循,最常規的手段是在頁面 URL 中設定一個引數,例如 http://www.example.com/index.html?iframe_hijack_redirected=1 ,其中 iframe_hijack_redirected=1
表示頁面已經被劫持過了,就不再巢狀 iframe 了。所以根據這個特性,我們可以改寫我們的 URL
,使之看上去已經被劫持了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
var
flag = 'iframe_hijack_redirected' ;
// 當前頁面存在於一個 iframe 中
// 此處需要建立一個白名單匹配規則,白名單預設放行
if
(self != top) {
var
// 使用 document.referrer 可以拿到跨域 iframe 父頁面的 URL
parentUrl = document.referrer,
length = whiteList.length,
i = 0;
for (; i<length; i++){
// 建立白名單正則
var
reg = new
RegExp(whiteList[i], 'i' );
// 存在白名單中,放行
if (reg.test(parentUrl)){
return ;
}
}
var
url = location.href;
var
parts = url.split( '#' );
if
(location.search) {
parts[0] +=
'&'
+ flag + '=1' ;
}
else
{
parts[0] +=
'?'
+ flag + '=1' ;
}
try
{
console.log( '頁面被嵌入iframe中:' , url);
top.location.href = parts.join( '#' );
}
catch
(e) {}
}
|
當然,如果這個引數一改,防巢狀的程式碼就失效了。所以我們還需要建立一個上報系統,當發現頁面被巢狀時,傳送一個攔截上報,即便重定向失敗,也可以知道頁面嵌入 iframe 中的 URL,根據分析這些 URL ,不斷增強我們的防護手段,這個後文會提及。
內聯事件及內聯指令碼攔截
在 XSS 中,其實可以注入指令碼的方式非常的多,尤其是 HTML5 出來之後,一不留神,許多的新標籤都可以用於注入可執行指令碼。
列出一些比較常見的注入方式:
<a href="javascript:alert(1)" ></a>
<iframe src="javascript:alert(1)" />
<img src='x' onerror="alert(1)" />
<video src='x' onerror="alert(1)" ></video>
<div onclick="alert(1)" onmouseover="alert(2)" ><div>
除去一些未列出來的非常少見生僻的注入方式,大部分都是 javascript:...
及內聯事件 on*
。
我們假設注入已經發生,那麼有沒有辦法攔截這些內聯事件與內聯指令碼的執行呢?
對於上面列出的 (1) (5) ,這種需要使用者點選或者執行某種事件之後才執行的指令碼,我們是有辦法進行防禦的。
瀏覽器事件模型
這裡說能夠攔截,涉及到了事件模型
相關的原理。
我們都知道,標準瀏覽器事件模型存在三個階段:
- 捕獲階段
- 目標階段
- 冒泡階段
對於一個這樣 <a href="javascript:alert(222)" ></a>
的 a 標籤而言,真正觸發元素 alert(222)
是處於點選事件的目標階段。
點選上面的 click me
,先彈出 111 ,後彈出 222。
那麼,我們只需要在點選事件模型的捕獲階段對標籤內 javascript:...
的內容建立關鍵字黑名單,進行過濾審查,就可以做到我們想要的攔截效果。
對於 on* 類內聯事件也是同理,只是對於這類事件太多,我們沒辦法手動列舉,可以利用程式碼自動列舉,完成對內聯事件及內聯指令碼的攔截。
以攔截 a 標籤內的 href="javascript:...
為例,我們可以這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
// 建立關鍵詞黑名單
var
keywordBlackList = [
'xss' ,
'BAIDU_SSP__wrapper' ,
'BAIDU_DSPUI_FLOWBAR'
];
document.addEventListener( 'click' ,
function (e) {
var
code = "" ;
// 掃描 <a href="javascript:"> 的指令碼
if
(elem.tagName == 'A'
&& elem.protocol == 'javascript:' ) {
var
code = elem.href.substr(11);
if
(blackListMatch(keywordBlackList, code)) {
// 登出程式碼
elem.href =
'javascript:void(0)' ;
console.log( '攔截可疑事件:'
+ code);
}
}
},
true );
/**
* [黑名單匹配]
* @param {[Array]} blackList [黑名單]
* @param {[String]} value [需要驗證的字串]
* @return {[Boolean]} [false -- 驗證不通過,true -- 驗證通過]
*/
function
blackListMatch(blackList, value) {
var
length = blackList.length,
i = 0;
for
(; i < length; i++) {
// 建立黑名單正則
var
reg = new
RegExp(whiteList[i], 'i' );
// 存在黑名單中,攔截
if
(reg.test(value)) {
return
true ;
}
}
return
false ;
}
|
可以戳我檢視DEMO。(開啟頁面後開啟控制檯檢視 console.log)
點選圖中這幾個按鈕,可以看到如下:
這裡我們用到了黑名單匹配,下文還會細說。
靜態指令碼攔截
XSS 跨站指令碼的精髓不在於“跨站”,在於“指令碼”。
通常而言,攻擊者或者運營商會向頁面中注入一個<script>
指令碼,具體操作都在指令碼中實現,這種劫持方式只需要注入一次,有改動的話不需要每次都重新注入。
我們假定現在頁面上被注入了一個 <script src="http://attack.com/xss.js">
指令碼,我們的目標就是攔截這個指令碼的執行。
聽起來很困難啊,什麼意思呢。就是在指令碼執行前發現這個可疑指令碼,並且銷燬它使之不能執行內部程式碼。
所以我們需要用到一些高階 API ,能夠在頁面載入時對生成的節點進行檢測。
MutationObserver
MutationObserver 是 HTML5 新增的 API,功能很強大,給開發者們提供了一種能在某個範圍內的 DOM 樹發生變化時作出適當反應的能力。
說的很玄乎,大概的意思就是能夠監測到頁面 DOM 樹的變換,並作出反應。
MutationObserver()
該建構函式用來例項化一個新的Mutation觀察者物件。
1 2 3 |
MutationObserver(
function
callback
);
|
目瞪狗呆,這一大段又是啥?意思就是 MutationObserver 在觀測時並非發現一個新元素就立即回撥,而是將一個時間片段裡出現的所有元素,一起傳過來。所以在回撥中我們需要進行批量處理。而且,其中的 callback
會在指定的
DOM 節點(目標節點)發生變化時被呼叫。在呼叫時,觀察者物件會傳給該函式兩個引數,第一個引數是個包含了若干個 MutationRecord 物件的陣列,第二個引數則是這個觀察者物件本身。
所以,使用 MutationObserver ,我們可以對頁面載入的每個靜態指令碼檔案,進行監控:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// MutationObserver 的不同相容性寫法
var
MutationObserver = window.MutationObserver || window.WebKitMutationObserver ||
window.MozMutationObserver;
// 該建構函式用來例項化一個新的 Mutation 觀察者物件
// Mutation 觀察者物件能監聽在某個範圍內的 DOM 樹變化
var
observer = new
MutationObserver( function (mutations) {
mutations.forEach( function (mutation) {
// 返回被新增的節點,或者為null.
var
nodes = mutation.addedNodes;
for
( var
i = 0; i < nodes.length; i++) {
var
node = nodes[i];
if
(/xss/i.test(node.src))) {
try
{
node.parentNode.removeChild(node);
console.log( '攔截可疑靜態指令碼:' , node.src);
}
catch
(e) {}
}
}
});
});
// 傳入目標節點和觀察選項
// 如果 target 為 document 或者 document.documentElement
// 則當前文件中所有的節點新增與刪除操作都會被觀察到
observer.observe(document, {
subtree:
true ,
childList:
true
});
|
可以看到如下:可以戳我檢視DEMO。(開啟頁面後開啟控制檯檢視 console.log)
<script type="text/javascript" src="./xss/a.js"></script>
是頁面載入一開始就存在的靜態指令碼(檢視頁面結構),我們使用 MutationObserver 可以在指令碼載入之後,執行之前這個時間段對其內容做正則匹配,發現惡意程式碼則 removeChild()
掉,使之無法執行。
使用白名單對 src 進行匹配過濾
上面的程式碼中,我們判斷一個js指令碼是否是惡意的,用的是這一句:
1 |
if
(/xss/i.test(node.src)) {}
|
當然實際當中,注入惡意程式碼者不會那麼傻,把名字改成 XSS 。所以,我們很有必要使用白名單進行過濾和建立一個攔截上報系統。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// 建立白名單
var
whiteList = [
'www.aaa.com' ,
'res.bbb.com'
];
/**
* [白名單匹配]
* @param {[Array]} whileList [白名單]
* @param {[String]} value [需要驗證的字串]
* @return {[Boolean]} [false -- 驗證不通過,true -- 驗證通過]
*/
function
whileListMatch(whileList, value) {
var
length = whileList.length,
i = 0;
for
(; i < length; i++) {
// 建立白名單正則
var
reg = new
RegExp(whiteList[i], 'i' );
// 存在白名單中,放行
if
(reg.test(value)) {
return
true ;
}
}
return
false ;
}
// 只放行白名單
if
(!whileListMatch(blackList, node.src)) {
node.parentNode.removeChild(node);
}
|
這裡我們已經多次提到白名單匹配了,下文還會用到,所以可以這裡把它簡單封裝成一個方法呼叫。
動態指令碼攔截
上面使用 MutationObserver 攔截靜態指令碼,除了靜態指令碼,與之對應的就是動態生成的指令碼。
1 2 3 4 5 |
var
script = document.createElement( 'script' );
script.type =
'text/javascript' ;
script.src =
'http://www.example.com/xss/b.js' ;
document.getElementsByTagName( 'body' )[0].appendChild(script);
|
要攔截這類動態生成的指令碼,且攔截時機要在它插入 DOM 樹中,執行之前,本來是可以監聽 Mutation
Events
中的 DOMNodeInserted
事件的。
Mutation Events 與 DOMNodeInserted
開啟 MDN ,第一句就是:
該特性已經從 Web 標準中刪除,雖然一些瀏覽器目前仍然支援它,但也許會在未來的某個時間停止支援,請儘量不要使用該特性。
雖然不能用,也可以瞭解一下:
1 2 3 4 5 6 7 |
document.addEventListener( 'DOMNodeInserted' ,
function (e) {
var
node = e.target;
if
(/xss/i.test(node.src) || /xss/i.test(node.innerHTML)) {
node.parentNode.removeChild(node);
console.log( '攔截可疑動態指令碼:' , node);
}
}, true );
|
然而可惜的是,使用上面的程式碼攔截動態生成的指令碼,可以攔截到,但是程式碼也執行了:DOMNodeInserted
顧名思義,可以監聽某個 DOM 範圍內的結構變化,與 MutationObserver
相比,它的執行時機更早。
但是 DOMNodeInserted
不再建議使用,所以監聽動態指令碼的任務也要交給 MutationObserver
。
可惜的是,在實際實踐過程中,使用 MutationObserver
的結果和 DOMNodeInserted
一樣,可以監聽攔截到動態指令碼的生成,但是無法在指令碼執行之前,使用 removeChild
將其移除,所以我們還需要想想其他辦法。
重寫 setAttribute 與 document.write
重寫原生 Element.prototype.setAttribute 方法
在動態指令碼插入執行前,監聽 DOM 樹的變化攔截它行不通,指令碼仍然會執行。
那麼我們需要向上尋找,在指令碼插入 DOM 樹前的捕獲它,那就是建立指令碼時這個時機。
假設現在有一個動態指令碼是這樣建立的:
1 2 3 4 5 |
var
script = document.createElement( 'script' );
script.setAttribute( 'type' ,
'text/javascript' );
script.setAttribute( 'src' ,
'http://www.example.com/xss/c.js' );
document.getElementsByTagName( 'body' )[0].appendChild(script);
|
而重寫 Element.prototype.setAttribute
也是可行的:我們發現這裡用到了
setAttribute 方法,如果我們能夠改寫這個原生方法,監聽設定 src
屬性時的值,通過黑名單或者白名單判斷它,就可以判斷該標籤的合法性了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// 儲存原有介面
var
old_setAttribute = Element.prototype.setAttribute;
// 重寫 setAttribute 介面
Element.prototype.setAttribute =
function (name, value) {
// 匹配到 <script src='xxx' > 型別
if
( this .tagName ==
'SCRIPT'
&& /^src$/i.test(name)) {
// 白名單匹配
if
(!whileListMatch(whiteList, value)) {
console.log( '攔截可疑模組:' , value);
return ;
}
}
// 呼叫原始介面
old_setAttribute.apply( this , arguments);
};
// 建立白名單
var
whiteList = [
'www.yy.com' ,
'res.cont.yy.com'
];
/**
* [白名單匹配]
* @param {[Array]} whileList [白名單]
* @param {[String]} value [需要驗證的字串]
* @return {[Boolean]} [false -- 驗證不通過,true -- 驗證通過]
*/
function
whileListMatch(whileList, value) {
var
length = whileList.length,
i = 0;
for
(; i < length; i++) {
// 建立白名單正則
var
reg = new
RegExp(whiteList[i], 'i' );
// 存在白名單中,放行
if
(reg.test(value)) {
相關推薦【前端安全】JavaScript防http劫持與XSS作為前端,一直以來都知道HTTP劫持與XSS跨站指令碼(Cross-site scripting)、CSRF跨站請求偽造(Cross-site request forgery)。但是一直都沒有深入研究過,前些日子同事的分享會偶然提及,我也對這一塊很感興趣,便深入研究了一番。 【前端安全】JavaScript防流量劫持劫持產生的原因和方式 在網頁開發的訪問過程中,http是我們主要的訪問協議。我們知道http是一種無狀態的連線。即沒有驗證通訊雙方的身份,也沒有驗證資訊的完整性,所以很容易受到篡改。運營商就是利用了這一點篡改了使用者正常訪問的網頁,插入廣告或者其他一些雜七雜八的東西,達到盈利的目的。 運營商的一般做法有以 【前端安全】JavaScript防XSS攻擊什麼是XSS XSS(Cross Site Scripting),跨站指令碼攻擊,是一種允許攻擊者在另外一個使用者的瀏覽器中執行惡意程式碼指令碼的指令碼注入式攻擊。本來縮小應該是CSS,但為了和層疊樣式(Cascading Style Sheet,CSS)有所區分,故稱XS 【前端筆試】JavaScript實現字串全排列我個人認為前端工程師筆試題中,演算法題一般不難,也就這個難度,甚至比這還要簡單。這是我在筆試過程中遇到的一個題~下面分享一下解題思路。 大體結構:定義一個方法,傳入str變數,返回一個數組,包含所有排列: function fun(str){ v 【網路安全】關於網路劫持的一些客戶端解決方案最近遇到了一個關於網路劫持的問題,簡單來說,是客戶端訪問阿里雲主機,以及客戶端從阿里雲端儲存上進行下載的時候,出現的資料異常問題。 現象就是,例如我訪問一個阿里雲主機上的介面,介面有的時候返回的值不是我想要的值,比如說一堆亂碼,還有從雲端儲存上下載一個APK檔案,下載下來之 【前端開發】合併多個前端靜態資原始檔,減少HTTP請求次數從優化請求靜態資原始檔(JS、CSS)的角度來說,載入多個檔案會發出多次請求,為了解決這個問題,我們可以把多個檔案合併成一個檔案,現在有一些前端工具可以把多個檔案合併成一個檔案,這種方式是靜態的在發版前就要合併成一個檔案,還有一種方式把多個檔案動態合併成一個檔案;所謂動態是把 【滲透課程】前言-揭開Web滲透與安全的面紗(必看)blank 可見 box 網站 大致 物理 org 知識點 get 服務器是怎麽被入侵的 攻擊者想要對一臺計算機滲透必須具備以下條件: 1、服務器與客戶端能夠正常通訊 (服務器是為客戶端提供服務的) 2、服務器向客戶端提供的權限(服務)或者說是端口。 服務端所提供的服務 早 【 js 基礎 】Javascript “繼承”一份 類繼承 屬性。 淺拷貝 創建 生成 特殊 並不會 也會 【 js 基礎 】Javascript “繼承” 是時候寫一寫 “繼承”了,為什麽加引號,因為當你閱讀完這篇文章,你會知道,說是 繼承 其實是不準確的。 一、類1、傳統的面向類的語言中的類:類/繼承 描述 【Android安全】Android中的“SpyLocker”惡意軟件 - 您需要知道的內容編譯參數 agen 詳細 通過 來源 永遠 鎖屏 mob shtml SpyLocker惡意軟件是對Android安全應用的最新威脅,幾維安全詳細介紹了您需要了解的信息,以幫助您保護設備。此外,如果您的設備受到感染,幾維安全最新的應用程序將幫助您掃描,檢測和刪除SpyLoc 【幹貨】JavaScript DOM編程藝術學習筆記4-6ext 屬性節點 另一個 機器 rep lin bsp 每次 增加 四、案例研究:JavaScript圖片庫 js: function showPic(whichpic){ //取得鏈接 var source=whichpic.getAttribute("hr 【學習隨筆】web url http 初涉面向對象 服務器端 oca 包含 conn 接收 -a inter 無法 關於web,在最開始,每一臺計算機都是分離獨立的,各自完成各自的任務與工作,期間沒有任何交互聯系,彼此之間無法獲取信息。例如,A機上的程序,B機可能沒有,若B機想要使用這個程序,那麽就需要安裝和A機相 【前端筆記】? CSScad 偽類 round 什麽 發的 index light 選擇器 ima 1. 什麽是CSS CSS的全稱是Cascading Style Sheets,層疊樣式表。它用來控制HTML標簽的樣式,在美化網頁中起到非常重要的作用。 CSS的編寫格式是鍵 【前端技術】nodejs安裝擴展插件,總是報錯enoent的解決方案擴展 執行 src 自動填充 install image 都是 切換 -s 在某一目錄下使用npm install安裝擴展插件時,老是系統提示“npm install Error: ENOENT,no such file or directory; 以前都是很順利的安裝過 【前端基礎】動態腳本與JSONP技術 動態生成 查詢 pen 想想 一行代碼 art 構建 dom元素 博主入職兩個月了,越來越感受到打好基礎對於前端工程師的重要性,在向著狂拽酷炫的框架&構建工具狂飈之前,必須有一個堅實的基礎打底,才不至於輕易翻車。所以博主最近一直在惡補《JS高級程序設計》,發現 【前端框架】Django補充backends 操作 list 處理器 指定 lib 超時時間 unix decorator 一、緩存 由於Django是動態網站,所以每次請求均會去取到數據進行相應的操作,當程序訪問量大時,耗時必然會更加明顯,最簡單的解決方式就是使用緩存,緩存將某個views返回的 【前端閱讀】——《活用PHP、MySQL建構Web世界》摘記之設計技巧簡化 return 下載 center src rto 響應 server pty 二、設計技巧 Programming的習慣因人而異,這裏只提供一些經驗,可以參考。 1、利用Include模塊化你的程序代碼 Include函數基本上說:就像是把另一個文件(HTM 【總結整理】javascript基礎入門學習(慕課網學習)節點 confirm pro remove prompt 例如 ref 存儲 基礎入門 https://www.imooc.com/learn/36 註意: javascript作為一種腳本語言可以放在html頁面中任何位置,但是瀏覽器解釋html時是按先後順序的,所以前面 【Web安全】DoS及其家族之前 能夠 AC web安全 .com 客戶端和服務器 沒有 bsp serve 不久前我分享過的Web安全概述獲得了大家的廣泛關註,說明大家對Web安全這一塊還是很關心的,因此木可大大將陸續推出目前常見的Web攻擊手段和對應的防範策略。本期向大家介紹的是DoS和它的家族 【計算機網絡】Web和HTTPrip 緩存 方式 進一步 rac 解決 支持 響應狀態 rom 第二章第二節 Web和HTTP 這一章中,我們需要討論5種重要的應用:Web、文件傳輸、電子郵件、目錄服務、P2P;這一節中,我們將討論Web和它的應用層協議HTTP。 Outline Web簡介 HTTP 【前端GUI】—— 前端設計稿切圖通用性標準前言:公司在前端組和視覺組交接設計稿切圖的時候,總會因為視覺組同事們對前端的實現原理不清楚而出現各種問題,在用的時候還得再次返工,前端組同事們一致覺得應該出一份《設計稿切圖通用性標準檔案》,這裡是我結合資料做出的一份總結。 1、切圖資源尺寸必須為雙數 &n |