Nodejs筆記

weixin_33785972發表於2017-01-31

Node基本

  1. node的最大特性莫過於基於事件驅動的非阻塞I/O模型。
  2. node通過事件驅動的方式處理請求,無須為每一個請求建立額外的對應執行緒,可以省掉建立執行緒和銷燬執行緒的開銷,同時作業系統在排程任務時因為執行緒較少,上下文切換的代價很低。這使得伺服器能夠有條不紊地處理請求,即使在大量連線的情況下,也不受執行緒上下文切換開銷的影響,這是Node高效能的一個原因。Apache會為每個請求啟動一個執行緒,每個執行緒會佔用一定記憶體,併發量較大時會緩慢。Nginx也使用和node一樣的事件驅動方式處理請求。
  3. node對引入過的模組都會進行快取,以減少二次引入時的開銷,node快取的是編譯和執行後的物件。不論是核心模組還是檔案模組,require( )方法對相同模組的二次載入都一律採用快取優先的方式,這是第一優先順序的。不同之處在於核心模組的快取檢查先於檔案模組的快取檢查。
  4. 事件輪詢:從本質上來說,node會先註冊事件,隨後不停地詢問核心這些時間是否已經分發。當事件分發時,對應的回撥函式就會被觸發,然後繼續執行下去。如果沒有事件觸發,則繼續執行其他程式碼,直到有新事件時,再去執行對應的回撥函式。
  5. 在程式中定義配置項如app.set(“photo”,__dirname+’/public/photos’)後就可以在各種環境下任意改變此目錄。
  6. 當node接收到從瀏覽器發來的http請求時,底層的TCP連線會分配一個檔案描述符。隨後,如果客戶端向伺服器傳送資料,node就會收到該檔案描述符上的通知,然後觸發JavaScript的回撥函式。
  7. 對於阻塞式I/O執行緒在執行中遇到磁碟讀寫或者資料庫通訊,網路通訊這種耗時比較多的時候,作業系統將會剝奪此執行緒的CPU資源,並暫停此執行緒,轉而去執行別的執行緒。非同步式I/O則針對所有操作採取不阻塞的方法,當執行緒遇到I/O操作時將操作傳送給作業系統,然後接著執行下一個操作,當作業系統執行完I/O操作之後,將以事件的方式通知執行I/O的執行緒,執行緒會在特定的時候執行這個事件。這一切的前提就是系統需要一個時間迴圈,以不斷地去查詢有沒有未處理的事件,然後交給預處理。對比與阻塞I/O,非同步模型極大提高了web伺服器的併發性。
  8. buffer是一個表示固定記憶體分配的全域性物件(即放到緩衝區的位元組數需要提前確定)
  9. node的HTTP伺服器是構建於node TCP伺服器之上的,即node中的HTTP.server繼承自net.server(net為TCP模組)。TCP的首要特性是它面向連線。
  10. Node中的管道可以讓資料流動到指定目的地(即WriteableStream)讀取一個檔案並寫入到另一個檔案中,利用pipe()作為連線,ReadableStream.pipe(WriteableStream).HTTP請求中在客戶端request就是一個WriteableStream,response為Readablestream,而在伺服器端則相反。
  11. node與作業系統互動的工具
    • 全域性的process物件————包含當前程式的相關資訊,如傳參和當前設定的環境變數
    • fs模組————包含底層的ReadStream和WriteStream類。
    • child_process模組————繁衍子程式的底層和高層介面,以及一種繁衍帶有雙向資訊傳遞通道node例項的特殊辦法。
  12. node內建了偵錯程式,控制檯輸入node debug app.js可以分步除錯程式,n(下一步)、s(步入)、o(步出)。n會跨過當前行:偵錯程式會執行這一行,但如果指令呼叫了其他函式,在這些函式執行完後才把控制權交還。s與之不同,如果呼叫其他函式會進入函式內部逐步執行。o允許跳出當前正在執行的函式。
  13. 也可以使用node探查器node-inspector,可以在瀏覽器內逐步除錯。

node的非同步I/O

  • 事件迴圈是非同步實現的核心,它與瀏覽器中的執行模型基本保持一致。

  • 在啟動node程式時會建立一個類似while(true)的迴圈,每執行一次迴圈體的過程我們稱之為Tick。每個Tick的過程就是檢視是否有事件待處理,如果有,就取出事件及其相關的回撥函式。如果存在關聯的回撥函式,就執行他們。然後進入下一個迴圈,如果不再有事件處理,就退出程式。

  • 事件迴圈是一個典型的生產者/消費者模型。非同步I/O、網路請求等則是事件的生產者,源源不斷為Node提供不同型別的事件,這些事件被傳遞到對應的觀察者那裡,事件迴圈則從觀察者那裡取出事件並處理。

  • 事實上,在node中,除了javascript是單執行緒的,Node本身其實是多執行緒的,只是I/O執行緒使用的CPU較少。除了使用者程式碼無法並行執行外,所有的I/O(磁碟I/O和網路I/O等)是可以並行起來的。

    非I/O的api setTimeout和setInterval

    • 定時器的問題在於它並非精準的(在容忍範圍內)。如果一次迴圈佔用的時間過多,那麼下次迴圈時可能會超時。如通過setTimeout設定一個任務在10毫秒之後執行,但是在9毫秒後,有個任務佔用了5毫秒的CPU時間片,再次輪到定時器執行時,時間就已經過期四毫秒。

Buffer物件

  • Buffer物件類似於陣列,它的元素為16進位制的兩位數,即0~255的數值。

  • Bufffer可以對字串的編碼進行轉換,通過字串建立一個buffer:new Buffer(str,[encoding]);若encoding不傳值預設utf8編碼。

  • buffer轉出字串,利用buffer.tostring([encoding],[start],[end]);

  • 在傳輸資料時經常使用trunk來表示表示buffer資料,data+=trunk;等價於data=data.tostring()+trunk.tostring();這個適用於傳輸內容為英文的資料,中文uft8編碼中佔三個位元組,如果中間隔開會出現亂碼。

  • 如果是socket通訊則可以使用socket.setEncoding([encoding])來設定接受資料的編碼格式。

  • 為了不亂碼,buffer的正確拼接方式是用一個陣列來儲存接收所有Buffer片段並記錄下所有片段的總長度,然後呼叫陣列的Buffer.concat()方法生成一個合併的buffer物件

var chunks = [];
var size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
var data = null;
switch(chunks.length) {
case 0: data = new Buffer(0);
break;
case 1: data = chunks[0];
break;
default:
data = new Buffer(size);
for (var i = 0, pos = 0, l = chunks.length; i < l; i++) {
var chunk = chunks[i];
chunk.copy(data, pos);
pos += chunk.length;
}
break;
}
});
```

函數語言程式設計

高階函式

  • 高階函式可以將函式作為輸入或者返回值,事件的回撥處理是基於高階函式的特性來完成的。高階函式可以讓事件十分方便地進行復雜業務邏輯的解耦。
  • 偏函式用法是指建立一個呼叫另外一個部分——引數或變數已經預製的函式——的函式的用法。實現方法類似於工廠模式通過指定部分引數來產生一個新的定製函式。

偏函式

  • 偏函式你可以理解為工廠函式,也就是這種函式是用來當做模板來生產出函式的,因為作為一等公民,函式可以作為返回值。

  • 一個javascript對型別的判斷的例子:

    var toString = Object.prototype.toString;
    var isString = function (obj){
        return toString.call(obj) == '[object String]';
    };
    var isFunction = function(obj){
        return toString.call(obj) == '[object Function]';
    };
    

網路通訊

REST API

  • API與使用者的通訊協議,總是使用HTTPs協議。

  • 應該儘量將API部署在專用域名之下,或者主域名下:https://example.org/api/

  • 應該將API的版本號放入URL:https://api.example.com/v1/

  • 網址中不能有動詞,只能有名詞,而且所用的名詞往往與資料庫的表格名對應。一般來說,資料庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應該使用複數。

  • 對於資源的具體操作型別,由HTTP動詞表示。常用的HTTP動詞有下面五個(括號裡是對應的SQL命令)。

    GET(SELECT):從伺服器取出資源(一項或多項)
    POST(CREATE):在伺服器新建一個資源
    PUT(UPDATE):在伺服器更新資源(客戶端提供改變後的完整資源)
    PATCH(UPDATE):在伺服器更新資源(客戶端提供改變的屬性)
    DELETE(DELETE):從伺服器刪除資源
    
  • 如果記錄數量很多,伺服器不可能都將它們返回給使用者。API應該提供引數,過濾返回結果。
    下面是一些常見的引數。

    ?limit=10:指定返回記錄的數量
    ?offset=10:指定返回記錄的開始位置。
    ?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。
    ?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序。
    ?animal_type_id=1:指定篩選條件
    
  • 伺服器向使用者返回的狀態碼和提示資訊,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)

    200 OK - [GET]:伺服器成功返回使用者請求的資料,該操作是冪等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:使用者新建或修改資料成功。
    202 Accepted - [*]:表示一個請求已經進入後臺排隊(非同步任務)
    204 NO CONTENT - [DELETE]:使用者刪除資料成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:使用者發出的請求有錯誤,伺服器沒有進行新建或修改資料的操作,該操作是冪等的。
    401 Unauthorized - [*]:表示使用者沒有許可權(令牌、使用者名稱、密碼錯誤)。
    403 Forbidden - [*] 表示使用者得到授權(與401錯誤相對),但是訪問是被禁止的。
    404 NOT FOUND - [*]:使用者發出的請求針對的是不存在的記錄,伺服器沒有進行操作,該操作是冪等的。
    406 Not Acceptable - [GET]:使用者請求的格式不可得(比如使用者請求JSON格式,但是隻有XML格式)。
    410 Gone -[GET]:使用者請求的資源被永久刪除,且不會再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個物件時,發生一個驗證錯誤。
    500 INTERNAL SERVER ERROR - [*]:伺服器發生錯誤,使用者將無法判斷髮出的請求是否成功。
    
  • 針對不同操作,伺服器向使用者返回的結果應該符合以下規範。

    GET /collection:返回資源物件的列表(陣列)
    GET /collection/resource:返回單個資源物件
    POST /collection:返回新生成的資源物件
    PUT /collection/resource:返回完整的資源物件
    PATCH /collection/resource:返回完整的資源物件
    DELETE /collection/resource:返回一個空文件
    
  • RESTful API最好做到Hypermedia,即返回結果中提供連結,連向其他API方法,使得使用者不查文件,也知道下一步應該做什麼。

  • node提供net、dgram、http、https模組來建立TCP、UDP、HTTP、HTTPS伺服器。

webSocket

  • 瀏覽器通過在請求頭中新增Upgrade:webSockt和Connection:Upgrade來表示請求伺服器端升級協議為websockt。通常使用Sec-WebSockt-Key用於安全校驗。

HTTPS

  • SSL作為一種安全協議,在傳輸層提供對網路連線加密的功能,對應用層而言是透明的,資料在傳遞到應用層之前就已經完成了加密和解密的過程。
  • node在網路安全方面提供了三個模組:
    • crypto主要用於加密解密,SHA1和MD5等演算法。
    • tls提供了與net模組類似的功能,區別在於建立的是TLS/SSL加密的TCP連線上。
    • https與http模組介面一致,區別在於建立安全的連線。

Node使用

  1. 在node中定義了靜態檔案app.use(express.static(path))之後如果要用裡面資料可以直接使用以/開頭的靜態檔案相對路徑。

  2. node刪除file使用fs.unlink( )!

  3. node中fs.stat( )系統呼叫獲取檔案的相關資訊,比如修改時間、位元組數等,如果檔案不存在fs.stat()會在err.code中放入ENOOENT作為響應。

  4. app.use('/api',api.auth)這是掛載點,即任何以/api開頭的請求路徑名和HTTP謂詞都會導致這個中介軟體被呼叫。

  5. node中引入crypto模組用於加密

    function sha1(str){
    

var md5sum = crypto.createHash("sha1");
md5sum.update(str);
str = md5sum.digest("hex");
return str;
}

```
  1. 模組內引用路徑時一定要使用絕對路徑,藉助於全域性變數__dirname與__filename來使用。因為當主函式使用模組時若是相對路徑則以主函式作為參考。

  2. 標準庫元件url可以補全地址url.resolve(主站url,href)。

  3. node中的全域性函式process.argv為一個argument的陣列索引為零的儲存的是node所在資料夾,索引為1的是當前執行檔案路徑,後面的索引為在命令列啟動node時傳入的引數。

  4. 模組匯出時用module.exports={函式名}的形式,匯入模組時即使在同一目錄下也需要在開頭加“./檔名.js”若不加./則優先在內建模組中尋找,然後是在node_modules資料夾中尋找。

  5. 絕大部分node非同步API接收的回撥函式,第一個引數都是錯誤物件或者是null。

  6. Event模組時node對‘釋出/訂閱’模式的實現,其中提供了一個EventEmitter物件,核心事件就是事件的觸發與事件監聽功能的封裝。

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter; //初始化物件
emitter.on(‘自定義事件名’,function(){}) //繫結事件
emitter.emit(‘事件名’,‘回撥函式的引數’) // 觸發事件
```

  1. 使用net.creatServer( function(socket){})時候回撥函式傳回來的是一個socket物件,可以通過給socket物件setEncoding來設定接收到的流的顯示方式。socket.on(‘data’,回撥函式)來給socket繫結接受到資料時觸發的事件。
  2. fs.createReadStream('fire.jpg').pipe(respond);在http中通過流的方式給頁面中傳圖片。
  3. node中http會將所有主機名後面的內容放入request.url中.
  4. node提供querystring的模組,該模組含有一個.parse( )方法,傳入引數如“q=1”的字串返回一個{q:1}的物件。這個解析處理方式和Node解析header訊息的方法類似,node將http請求資料中的header資訊從字串解析成一個方便處理的header物件。同樣可以使用querystring.stringfy({q:1})將物件轉為字串。
  5. 在http的請求中一般通過給respond繫結data事件來獲取返回的資料,繫結end事件等待資料獲取完後執行相應操作。
  6. node在設定登入頁面時,如果用到了第三方認證如微博QQ等登入可以使用passport模組,方便配置各種型別的OAuth。
  7. express客戶端使用socket.io要引入socket.io給客戶端寫的js檔案<script src='/socket.io/socket.io.js'></script>
  8. express中使用socket.io模組,如果要群發資訊則需要每個客戶端都加入到同一房間內,使用socket.join(‘房間名’);來加入房間,然後使用socket.to(‘房間名’).emit(‘event’,fn)來廣播訊息,訊息預設只對除當前客戶端之外的所有客戶端傳送,如果還要對當前客戶端傳送則再加上socket.emit(‘event’,fn)。可以利用socket.rooms來檢視客戶端所在的房間,返回一個物件。一個客戶端可以在多個房間,第一個房間與客戶端的id相同,是一個隨機的字串,如果要針對某個客戶端單獨發訊息可以用to指向客戶端所對應的專屬房間。
  9. express中路由和中介軟體的新增順序至關重要,如果把404處理器放在所有路由上面,首頁和相關頁面就無法顯示。自己編寫中介軟體時如果方法後面沒有呼叫next()則不會再執行之後的中介軟體。使用app.use(‘/url’,中介軟體),第一個參數列示當url字首與之匹配是才會呼叫後面的中介軟體。
  10. bodyParser()元件用於解析POST請求,它提供了req.body屬性,可以用來解析註冊資訊如JSON、x-www-form-urlencoded(HTML表單的預設值)和multipart/form-data請求。如果是multipart/form-data請求,如檔案上傳,則還有req.files物件。
  11. query()元件主要用於解析GET請求,它提供req.query物件將url中的GET資料轉化成一個物件存在req.query中。
  12. cheerio元件為一個 Node.js 版的 jquery,用來從網頁中以 css selector 取資料,使用方式跟 jquery 一樣一樣的。在爬蟲應用中使用superagent.get()得到網頁的資料srea之後利用cheerio 來將資料解析var $ = cheerio.load(sres.text);之後通過$(‘.’)方式來獲取DOM。
  13. 一定要注意superagent使用的是非同步請求,會在傳送去請求後繼續執行下面程式碼而非在獲得請求結果後。
  14. 利用eventproxy元件針對多個非同步請求統一處理回撥函式,無深度巢狀。用來檢測多個非同步操作是否完成,完成之後,會自動呼叫處理函式,並將抓取到的資料當引數傳過來。
  15. 當你需要去多個源(一般是小於 10 個)彙總資料的時候,用 eventproxy 方便;當你需要用到佇列,需要控制併發數,或者你喜歡函數語言程式設計思維時,使用 async做非同步處理。
  16. nodemon這個庫是專門除錯時候使用的,它會自動檢測node.js 程式碼的改動,然後幫你自動重啟應用。在除錯時可以完全用 nodemon 命令代替 node 命令。$ nodemon app.js 啟動應用。
  17. 上傳大型檔案時可以使用formidable的流式解析器,它可以隨著資料塊的上傳接收它們並呈現特定的部分這種方式不僅快,還不會因為需要大量的緩衝而導致記憶體膨脹,即便像視訊這種大型檔案,也不會把程式壓垮。
  18. 管理使用者密碼檔案時所謂加Salt,就是加點“佐料”。當使用者首次提供密碼時(通常是註冊時),由系統自動往這個密碼里加一些“Salt值”,這個值是由系統隨機生成的,並且只有系統知道。然後再雜湊。而當使用者登入時,系統為使用者提供的程式碼撒上同樣的“Salt值”,然後雜湊,再比較雜湊值,已確定密碼是否正確。這樣,即便兩個使用者使用了同一個密碼,由於系統為它們生成的salt值不同,他們的雜湊值也是不同的。即便黑客可以通過自己的密碼和自己生成的雜湊值來找具有特定密碼的使用者,但這個機率太小了(密碼和salt值都得和黑客使用的一樣才行)。參看express的auth示例。
  19. Post/Redirect/Get(PRG)模式是一個常用的web程式設計模式。在這種模式中,使用者請求表單,用HTTP/POST請求表單資料,然後使用者被重定向到另外一個web頁面上。被重定向到哪裡取決於表單資料是否有效。如果表單資料無效,程式會讓使用者回到表單頁面。如果表單資料有效,程式會讓使用者到新的頁面中。PRG模式主要是為了防止表單的重複提交。
  20. 在express中使用者被重定向後,res.locals中的內容會被重置。Server傳來訊息最好存在會話變數中。res.message函式可以吧訊息新增到任何Express請求的會話變數中。
  21. express.response物件是Express給相應物件的原型,向這個物件中新增屬性意味著所有的中介軟體和路由都能訪問它們。
  22. 使用res.redirect()時第一個引數可以填HTTP的Status Code,301重定向是“永久”的,意味著瀏覽器會快取重定向目標。如果使用301重定向並試圖第二次提交表單,瀏覽器會繞過整個處理程式並直接進入相應頁面。使用303重定向不會快取重定向目標。預設是302重定向。
  23. http中結束一次會話後記得呼叫res.end()結束請求,否則客戶端將一直處於等待狀態。

Async庫

Async庫是為了處理nodejs中的非同步任務,同樣也可以設定任務的同步執行流程。

使用async呼叫的函式必須是有一個callback引數,並在函式執行完後呼叫callback(null, "done!");第一個引數是error引數。如果任何一個函式向它的回撥函式中傳了一個error,則後面的函式都不會被執行,並且將會立刻會將該error以及已經執行了的函式的結果,傳給series中最後那個callback。

  1. series(tasks, [callback]) (多個函式依次執行,之間沒有資料交換)
  2. waterfall(tasks, [callback]) (多個函式依次執行,且前一個的輸出為後一個的輸入)
  3. parallel(tasks, [callback]) (多個函式並行執行)
  4. auto(tasks, [callback]) (多個函式有依賴關係,有的並行執行,有的依次執行)
  5. whilst(test, fn, callback)(用可於非同步呼叫的while)

BasicAuth庫

  • basicAuth中介軟體為網站新增身份認證功能,使用該中介軟體後,使用者訪問網站必須輸入使用者名稱和密碼並通過難後才能訪問網站。只提供最基本的訪問授權,並且只能通過HTTPS使用。只有在需要又快又容易的東西,並且在HTTPS時才用到BasicAuth。

路由引數

app.get(/staff/:name,function(){}) 

node中路由系統會將引數值放入req.params.name中。

ejs模板

  • 使用render來渲染輸出模板:ejs.render(str, data, options); // render的返回值是最終結果string
  • ejs中迴圈輸出
        <ul>  
          <% names.forEach(function(name){ %>  
            <li><%= name %></li>  
          <% }) %>  
        </ul>  

options

```

cache:true, //是否對結果進行快取(需要filename)
filename:"path", //cache的key,用於include指令中
scope:"this", //指定函式執行的上下文物件
debug:true, //輸出生成的函式體
compileDebug:false, //為false時,debug指令不會被編譯
client:"", //返回獨立的編譯後的函式
open:"<%", //指定開標籤
close:"%>", //指定閉標籤
```

  • 如果定義了一段ejs模板作為公共模板,現在想引用這段公共模板的話,可以用include指令,需要在options裡指定filename和傳入引數:include('user/show', {user: user})

  • 過濾器:用於將結果進一步加工的API:

    <p><%=: users | map:'name' | join %></p>    //注意起始的:和中間的|標記 
    

ejs.render(str, {
users: [
{ name: 'tj' },
{ name: 'mape' },
{ name: 'guillermo' }
]
});
// 結果是:<p>Tj, Mape, Guillermo</p>

child_process模組中的spawn和exec方法

  • 這兩個方法都可以被用來開啟一個子程式來執行其他的程式.

  • child_process.spaen會返回一個帶有stdout和stderr流的物件。你可以通過stdout流來讀取子程式返回給Node.js的資料。stdout擁有’data’,’end’以及一般流所具有的事件。當你想要子程式返回大量資料給Node時,比如說影象處理,讀取二進位制資料等等,你最好使用spawn方法。

  • child_process.spawn方法是“非同步中的非同步”,意思是在子程式開始執行時,它就開始從一個流總將資料從子程式返回給Node。

  • 比如說我們想從一個URL下載檔案,我們選擇使用curl工具,此時,我們就可以在Node中使用spawn執行curl工具,下面是具體程式碼:

    var file = fs.createWriteStream(DOWNLOAD_DIR + file_name);
    var curl = spawn('curl', [file_url]);
    // 為spawn例項新增了一個data事件
    curl.stdout.on('data', function(data) { file.write(data); });
    // 新增一個end監聽器來關閉檔案流
    curl.stdout.on('end', function(data) {
        file.end();
        console.log(file_name + ' downloaded to ' + DOWNLOAD_DIR);
    });
    // 當子程式退出時,檢查是否有錯誤,同時關閉檔案流
    curl.on('exit', function(code) {
        if (code != 0) {
            console.log('Failed: ' + code);
        }
    });
    
  • child_process.exec方法會從子程式中返回一個完整的buffer。預設情況下,這個buffer的大小應該是200k。如果子程式返回的資料大小超過了200k,程式將會崩潰,同時顯示錯誤資訊“Error:maxBuffer exceeded”。

  • child_process.exec方法是“同步中的非同步”,儘管exec是非同步的,它一定要等到子程式執行結束以後然後一次性返回所有的buffer資料。如果exec的buffer體積設定的不夠大,它將會以一個“maxBuffer exceeded”錯誤失敗告終。

    var child = exec(cmomand, function(err, stdout, stderr) {
        if (err) throw err;
        else console.log(file_name + ' downloaded to ' + DOWNLOAD_DIR);
    });
    

爬蟲

  1. __VIEWSTATE
    a) ViewState是ASP.NET中用來儲存WEB控制元件回傳時狀態值一種機制。在WEB窗體(FORM)的設定為runat="server",這個窗體(FORM)會被附加一個隱藏的屬性_VIEWSTATE。_VIEWSTATE中存放了所有控制元件在ViewState中的狀態值。 ViewState是類Control中的一個域,其他所有控制元件通過繼承Control來獲得了ViewState功能。它的型別是system.Web.UI.StateBag,一個名稱/值的物件集合。
    b) 當請求某個頁面時,ASP.NET把所有控制元件的狀態序列化成一個字串,然後做為窗體的隱藏屬性送到客戶端。當客戶端把頁面回傳時,ASP.NET分析回傳的窗體屬性,並賦給控制元件對應的值。
  2. __EVENTVALIDATION
    __EVENTVALIDATION只是用來驗證事件是否從合法的頁面傳送,只是一個數字簽名,所以一般很短。“id”屬性為“__EVENTVALIDATION”的隱藏欄位是ASP.NET 2.0的新增的安全措施。該功能可以阻止由潛在的惡意使用者從瀏覽器端傳送的未經授權的請求.
    為了確保每個回發和回撥事件來自於所期望的使用者介面元素,ASP.NET執行庫將在事件中新增額外的驗證層。伺服器端通過檢驗表單提交請求的內容,將其與“id”屬性為“__EVENTVALIDATION”隱藏欄位中的資訊進行匹配。根據匹配結果來驗證未在瀏覽器端新增額外的輸入欄位(有可能為使用者在瀏覽器端惡意新增的欄位),並且該值是在伺服器已知的列表中選擇的。ASP.NET執行庫將在生成期間建立事件驗證欄位,而這是最不可能獲取該資訊的時刻。像檢視狀態一樣,事件驗證欄位包含雜湊值以防止發生瀏覽器端篡改。
    說明:“id”屬性為“__EVENTVALIDATION”隱藏欄位一般在表單的最下方,如果表單在瀏覽器端尚未解析完畢時,使用者提交資料有可能導致驗證失敗。__EVENTVALIDATION與__VIEWSTATE一般可以在瀏覽器頁面原始碼中找到,作為form中被隱藏的標籤,與其他資料一同提交。
  3. 使用superagent得到response的cookie: JSON.stringify(res.header["set-cookie"]);
  4. 針對superagent獲取的網頁亂碼的情況,superagent-charset擴充套件了superagent的功能,使其可以手動指定編碼功能。
  5. MD5加密是一種不可逆加密演算法,使用MD5加密時相同內容以字串傳入與數字傳入得到的結果不同。

相關文章