Node學習入門篇(七):Connect自帶的中介軟體
本章內容
- 解析cookie、請求主體和查詢字串的中介軟體
- 實現Web程式核心功能的中介軟體
- 處理Web程式安全的中介軟體
- 提供靜態檔案服務的中介軟體
解析cookie、請求主體和查詢字串的中介軟體
常用中介軟體
注意:All node patches will be removed - all middleware should work without Connect and with similar frameworks like restify(connect內建中介軟體已經從connect中分離處理,使用時需要單獨安裝、引入)
cookie-parser
- 未簽名cookie
1) install
npm install cookie-parser
2) 常規(未簽名)cookie測試
var connect = require('connect');
var app = connect();
var cookieParser = require('cookie-parser')
app.use(cookieParser('sysuygm is cool'));
app.use(function(req, res) {
console.log(req.cookies);
console.log(req.signedCookies);
"cookie" :req.cookies,
"signedCookies":req.signedCookies
}));
});
3)客戶端結果
傳送
accept: application/json
accept-encoding: gzip, deflate
accept-language: en-US,en;q=0.8
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Authorization: Basic ZmFmYTpmYWZh
Cookie: foo= bar;bar=baz
收到
{
"cookie": {
"foo": "bar",
"bar": "baz",
"io": "GXHOFF8zxkVibldwAAAO"
},
"signedCookies": {}
}
- 簽名cookie
簽名cookie更適合敏感資料,因為用它可以驗證cookie資料的完整性,有助於防止中間人攻擊。有效的簽名cookie放在req.signedCookies
物件中。把兩個物件分開是為了體現開發者的意圖。如果把簽名的和未簽名的cookie放到同一個物件中,常規cookie可能就會被改造,仿冒簽名的cookie。
簽名cookie
看起來像tobi.DDm3AcVxE9oneYnbmpqxoyhyKsk
一樣,點號(.)左邊的是cookie
的值,右邊是在伺服器上用SHA-1 HMAC
生成的加密雜湊值(基於雜湊的訊息認證碼)。如果cookie
的值或者HMAC
被改變的話,Connect
的解籤會失敗
1) 使用簽名的cookie
cookieParser()中介軟體沒有提供任何通過Set-Cookie響應頭向HTTP客戶端寫出站cookie的功能。但Connect可以通過res.setHeader()函式寫入多個Set-Cookie響應頭
app.use(function(req, res) {
console.log(req.cookies);
// console.log(req.signedCookies);
res.setHeader('Set-Cookie',
'foo-bar;Expires=True,08 Jun 2021 10:18 GMT');
res.end(JSON.stringify( {'seccuss':true}));
});
2) curl 檢視
>curl http://localhost:3000/ -H "Cookie:foo-bar" --head
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: foo-bar;Expires=True,08 Jun 2021 10:18 GMT
Date: Sun, 15 Apr 2018 15:16:58 GMT
Connection: keep-alive
bodyParser():解析請求主體
- 假設你要用HTML標籤接受使用者上傳的檔案。用一行程式碼新增bodyParser()中介軟體就全齊了
- bodyParser()元件為你提供了req.body屬性,可以用來解析JSON、x-www-form-urlencoded和multipart/form-data請求
- 如果是multipart/form-data請求,比如檔案上傳,則還有req.files 物件
- 這是個非常有用的元件,實際上它整合了其他三個更小的元件:json(), urlencoded(), 和multipart()
1) 先安裝
npm install body-parser
2) 使用
var cookieParser = require('cookie-parser')
// app.use(bodyParser()); 最好是像下面那樣顯示指定子元件,否則會提示冗餘
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use(function(req, res) {
console.log(req.body.username);
// console.log(req.signedCookies);
res.end(JSON.stringify( {
'username':req.username,
'password':req.pass
}));
});
POST資料
{
"username": "caicai",
"pass":"sysuygm"
}
如果bodyParser()在記憶體中快取json和x-www-form-urlencoded請求主體,產生一個大字串,那攻擊者會不會做一個超級大的JSON請求主體對伺服器做拒絕服務攻擊呢?答案基本上是肯定的,所以Connect提供了limit()中介軟體元件。
limit():請求主體的限制
- limit()中介軟體元件的目的是幫助過濾巨型的請求
- 防止指令碼攻擊
(好像已經被丟棄了)
query():查詢字串解析
- 它解析查詢字串,為程式提供req.query物件
- 它會將請求傳送過來的查詢字串以JSON格式作為響應返回去
(似乎已經被廢棄?)
favicon():提供favicon
(似乎已經被廢棄?)
使用 serve-favicon
代替,用static-favicon
會提示:
(node:3324)
DeprecationWarning: static-icon deprecated; switch to module serve-favicon
使用firefox才能看到favicon!
::1 - - [Sun, 15 Apr 2018 16:55:37 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
undefined
::1 - - [Sun, 15 Apr 2018 16:59:42 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"
undefined
::1 - - [Sun, 15 Apr 2018 16:59:54 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"
logger():記錄請求
已被廢棄,現在用morgan
代替, 直接安裝morgan
body-parser deprecated bodyParser: use individual json/urlencoded middlewares connect.js:27:9
body-parser deprecated undefined extended: provide extended option ..\node_modules\body-parser\index.js:105:29
morgan deprecated undefined format: specify a format connect.js:30:9
morgan deprecated default format: use combined format connect.js:30:9
listening...
undefined
::1 - fafa [Sun, 15 Apr 2018 16:48:14 GMT] "POST /?username=pppp HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
vhost():虛擬主機
- vhost()(虛擬主機)中介軟體是一種通過請求頭Host路由請求的簡單、輕量的辦法
- 這項任務通常是由反向代理完成的,可以把請求轉發到執行在不同埠上的本地伺服器那裡
- vhost()元件在同一個Node程序中完成這一操作,它將控制權交給跟vhost例項關聯的Node HTTP伺服器
- 可使子域名在Express中更容易管理。
- 缺點:如果一個網站引發了崩潰,你的所有網站都會宕掉(因為它們都執行在同一個程序中)
session():會話管理
需要安裝 session-parser
,且在cookie-parser
前引入。
安全相關部分
basicAuth():HTTP基本認證
基本認證是非常簡單的HTTP認證機制,並且在使用時應該小心,因為如果不是通過HTTPS進行認證,使用者憑證很可能會被攻擊者截獲
basicAuth()在最新的connect中已無法使用,且無法單獨使用,似乎只有Express中才能使用。
app.use(basicAuth(connect.basicAuth(auth)));
^
TypeError: connect.basicAuth is not a function
at Object.<anonymous> (F:\後臺開發\wechat\lib\connect.js:30:27)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:188:16)
at bootstrap_node.js:609:3
csrf():跨站請求偽造防護
- 跨站請求偽造(CSRF)利用站點對瀏覽器的信任漏洞進行攻擊
- csrf()會生成一個包含24個字元的唯一ID,認證令牌,作為req.session._csrf附到使用者的會話上
- 這個令牌會作為隱藏的輸入控制元件_csrf出現在表單中,CSRF在提交時會驗證這個令牌
>npm install csrf
使用:
為了確保csrf()可以訪問req.body._csrf(隱藏輸入控制元件的值)和req.session._csrf,你要確保csrf()新增在了bodyParser()和session()的下面
app.use(favicon(__dirname + '/timg.ico'));
// app.use(basicAuth(connect.basicAuth(auth)));
app.use(cookieParser('private-key'));
app.use(session({
keys:['aaa','bbb','ccc'],
maxAge:360000*24,
name:'session'
}));
app.use(bodyParser());
//新增在bodyParser()和session()的下面
app.use(csrf());
app.use(morgan());
errorHandler():開發錯誤處理
- 可以基於請求頭域Accept提供詳盡的HTML、JSON和普通文字錯誤響應
- errorHandler()是要用在開發過程中的,不應該出現在生產環境中
安裝:
npm install errorhandler
example:
var connect = require('connect')
var errorhandler = require('errorhandler')
var app = connect()
if (process.env.NODE_ENV === 'development') {
// only use in development
app.use(errorhandler())
}
static():靜態檔案服務
- static()中介軟體實現了一個高效能的、靈活的、功能豐富的靜態檔案伺服器,支援HTTP快取機制、範圍請
- 有對惡意路徑的安全檢查,預設不允許訪問隱藏檔案(檔名以.開頭),會拒絕有害的null位元組
- static()本質上是一個非常安全的、完全能勝任的靜態檔案服務中介軟體,可以保證跟目前各種HTTP客戶端的相容
- 假定你的程式遵循典型的場景,要返回./public目錄下的靜態資原始檔