ホームページ > 記事 > ウェブフロントエンド > Express で Cookie パーサー ミドルウェアを使用する方法
この記事では主に、Express cookie-parser ミドルウェアの実装例の詳細な分析を紹介し、参考にさせていただきます。
cookie-parserは、Cookieの解析を実装するために使用されるExpressのミドルウェアであり、公式のスキャフォールディングに組み込まれているミドルウェアの1つです。
使い方はとても簡単ですが、使用中に時々問題が発生する可能性があります。これは通常、Express + cookie-parser の署名と検証メカニズムを理解していないことが原因で発生します。
この記事では、Express + cookie-parser の署名と検証の実装メカニズム、および cookie 署名が Web サイトのセキュリティをどのように強化するかについて詳しく説明します。
テキスト同期は、GitHub テーマ シリーズ「Nodejs Learning Notes」に含まれています
cookie-parser の使用法を見てみる最も簡単な例から始めましょう。ここでは設定が使用されます。
Cookie 設定: Express の組み込みメソッド res.cookie() を使用します。
Cookie 解析: Cookie パーサー ミドルウェアを使用します。
var express = require('express'); var cookieParser = require('cookie-parser'); var app = express(); app.use(cookieParser()); app.use(function (req, res, next) { console.log(req.cookies.nick); // 第二次访问,输出chyingp next(); }); app.use(function (req, res, next) { res.cookie('nick', 'chyingp'); res.end('ok'); }); app.listen(3000);
現在のシナリオでは、Cookie パーサー ミドルウェアは大まかに次のように実装されています:
app.use(function (req, res, next) { req.cookies = cookie.parse(req.headers.cookie); next(); });
セキュリティ上の理由から、通常は Cookie に署名する必要があります。
この例は、いくつかの注意点を加えて次のように書き直されます:
cookieParser が初期化されるとき、署名キーとしてシークレットで渡します。
Cookie を設定するときは、signed を true に設定して、これから設定される Cookie に署名します。
Cookieを取得する場合は、req.cookiesまたはreq.signedCookiesを通じて取得できます。
var express = require('express'); var cookieParser = require('cookie-parser'); var app = express(); // 初始化中间件,传入的第一个参数为singed secret app.use(cookieParser('secret')); app.use(function (req, res, next) { console.log(req.cookies.nick); // chyingp console.log(req.signedCookies.nick); // chyingp next(); }); app.use(function (req, res, next) { // 传入第三个参数 {signed: true},表示要对cookie进行摘要计算 res.cookie('nick', 'chyingp', {signed: true}); res.end('ok'); }); app.listen(3000);
署名前のCookie値はchyingp
、署名後のCookie値はs%3Achyingp.uVofnk6k%2B9mHQpdPlQeOfjM8B5oa6mppny9d%2BmG9rD0
、デコード後のCookie値は :chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0 。 chyingp
,签名后的cookie值为 s%3Achyingp.uVofnk6k%2B9mHQpdPlQeOfjM8B5oa6mppny9d%2BmG9rD0
,decode后为 s:chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0
。
下面就来分析下,cookie的签名、解析是如何实现的。
Express完成cookie值的签名, cookie-parser 实现签名cookie的解析。两者共用同一个秘钥。
cookie签名
Express对cookie的设置(包括签名),都是通过 res.cookie() 这个方法实现的。
精简后的代码如下:
res.cookie = function (name, value, options) { var secret = this.req.secret; var signed = opts.signed; // 如果 options.signed 为true,则对cookie进行签名 if (signed) { val = 's:' + sign(val, secret); } this.append('Set-Cookie', cookie.serialize(name, String(val), opts)); return this; };
sign 为签名函数。伪代码如下,其实就是把cookie的原始值,跟hmac后的值拼接起来。
敲黑板划重点:签名后的cookie值,包含了原始值。
function sign (val, secret) { return val + '.' + hmac(val, secret); }
这里的 secret
哪来的呢?是 cookie-parser
初始化的时候传入的。如下伪代码所示:
var cookieParser = function (secret) { return function (req, res, next) { req.secret = secret; // ... next(); }; }; app.use(cookieParser('secret'));
签名cookie解析
知道了cookie签名的机制后,如何"解析"签名cookie就很清楚了。这个阶段,中间件主要做了两件事:
将签名cookie对应的原始值提取出来
验证签名cookie是否合法
实现代码如下:
// str:签名后的cookie,比如 "s:chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0" // secret:秘钥,比如 "secret" function signedCookie(str, secret) { // 检查是否 s: 开头,确保只对签过名的cookie进行解析 if (str.substr(0, 2) !== 's:') { return str; } // 校验签名的值是否合法,如合法,返回true,否则,返回false var val = unsign(str.slice(2), secret); if (val !== false) { return val; } return false; }
判断、提取cookie原始值比较简单。只是是 unsign 方法名比较有迷惑性。
一般只会对签名进行合法校验,并没有所谓的反签名。
unsign
方法的代码如下:
首先,从传入的cookie值中,分别提取出原始值A1、签名值B1。
其次,用同样的秘钥对A1进行签名,得到A2。
最后,根据A2、B1是否相等,判断签名是否合法。
exports.unsign = function(val, secret){
var str = val.slice(0, val.lastIndexOf('.')) , mac = exports.sign(str, secret); return sha1(mac) == sha1(val) ? str : false; };
主要是出于安全考虑, 防止cookie被篡改 ,增强安全性。
举个小例子来看下cookie签名是如何实现防篡改的。
基于前面的例子展开。假设网站通过 nick 这个cookie来区分当前登录的用户是谁。在前面例子中,登录用户的cookie中,nick对应的值如下:(decode后的)
s:chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0
此时,有人试图修改这个cookie值,来达到伪造身份的目的。比如修改成 xiaoming :
s:xiaoming.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0
当网站收到请求,对签名cookie进行解析,发现签名验证不通过。由此可判断,cookie是伪造的。
hmac("xiaoming", "secret") !== "uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0"
秘密
はどこから来たのでしょうか?これは、 cookie-parser
が初期化されるときに渡されます。次の疑似コードに示すように: 🎜rrreee🎜🎜署名付き Cookie の解析🎜🎜🎜 Cookie 署名のメカニズムを理解すると、署名付き Cookie を「解析」する方法が明確になります。この段階で、ミドルウェアは主に 2 つのことを行います: 🎜🎜🎜🎜署名付き Cookie に対応する元の値を抽出します 🎜🎜🎜🎜 署名付き Cookie が正当かどうかを検証します 🎜🎜🎜🎜 実装コードは次のとおりです: 🎜rrreee🎜Judge Cookie の元の値を抽出します。値は比較的単純です。 unsign メソッドの名前がわかりにくいだけです。 🎜🎜一般に、署名は法的に検証されるだけであり、いわゆる副署名はありません。 🎜🎜unsign
メソッドのコードは次のとおりです。 🎜🎜🎜🎜 まず、受信した Cookie 値から元の値 A1 と署名値 B1 を抽出します。 🎜🎜🎜🎜 次に、同じ秘密鍵を使用して A1 に署名し、A2 を取得します。 🎜🎜🎜🎜最後に、A2とB1が等しいかどうかに基づいて、署名が正当であるかどうかを判断します。 🎜🎜🎜🎜exports.unsign = function(val, Secret){🎜rrreee🎜🎜🎜Cookie署名の役割🎜🎜🎜🎜は主にセキュリティ上の理由から、Cookieの改ざんを防ぎセキュリティを強化します。 🎜🎜 Cookie 署名が改ざんをどのように防止できるかを簡単な例で見てみましょう。 🎜🎜前の例に基づいて展開します。 Web サイトがニック Cookie を使用して、現在ログインしているユーザーを区別すると仮定します。前の例では、ログイン ユーザーの Cookie で、対応するニックネームの値は次のとおりです: (デコード後)🎜🎜s:chyingp.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0
🎜🎜これであるとき、誰かが ID を偽造するという目的を達成するために、この Cookie の値を変更しようとしました。たとえば、これを xiaoming に変更します: 🎜🎜s:xiaoming.uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0
🎜🎜 Web サイトがリクエストを受信すると、署名 Cookie を解析し、署名の検証が失敗したことがわかります。このことからクッキーは偽造されたものであると判断できる。 🎜🎜hmac("xiaoming", "secret") !== "uVofnk6k+9mHQpdPlQeOfjM8B5oa6mppny9d+mG9rD0"
🎜🎜🎜🎜署名はセキュリティを保証しますか🎜🎜🎜🎜もちろんそうではありません。 🎜前のセクションの例では、ニックネーム Cookie の値のみを使用して、どのユーザーがログインしているかを判断しています。これは非常に悪い設計です。ただし、秘密鍵が不明な場合、署名付き Cookie を偽造することは困難です。ただし、ユーザー名が同じ場合、署名も同じになります。この場合、実際には偽造するのは非常に簡単です。
上記は私があなたのためにまとめたものです。
関連記事:
ネイティブ JavaScript を使用して虫眼鏡効果を実現する
以上がExpress で Cookie パーサー ミドルウェアを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。