nodejs express-jwt解析

18417 ワード

作用は何ですか
express-jwtはnodejsの中間部品で、彼はhttp要求のJson WebTokensの有効性を検証しにきました.有効であれば、Json WebTokensの値をreq.userの中に設定して、それから対応するrouterにルーティングします.このモジュールは、Node.jsアプリケーション内のJWTトークンを使用してHTTP要求を検証することができます.JWTは通常、APIエンドポイントを保護するために使用される.
express-jwtとjsonwebtokenはどういう関係ですか?
express-jwtの内部はjsonwebtokenを引用して、それに対してカプセル化して使います.実際のプロジェクトではこの二つは引用が必要で、彼らの位置付けは違っています.jsonwebtokenは、クライアントにtokenを生成するためのもので、express-jwtはtokenを検証するためのものです.
どう使いますか
インストール
npm install express-jwt
保護が必要なAPIを設定します.
var expressJWT = require('express-jwt');

var secretOrPrivateKey = "hello  BigManing"  //  token   token    
app.use(expressJWT({
    secret: secretOrPrivateKey   
}).unless({
    path: ['/getToken']  //      ,   URL     
}));
tokenの検証に失敗した場合の処理

app.use(function (err, req, res, next) {
  if (err.name === 'UnauthorizedError') {   
      //                  (    err      )
    res.status(401).send('invalid token...');
  }
});
  • tokenが失効したときのerr値:
    {
        "name": "UnauthorizedError",
        "message": "jwt expired",
        "code": "invalid_token",
        "status": 401,
        "inner": {
            "name": "TokenExpiredError",
            "message": "jwt expired",
            "expiredAt": "2017-08-03T10:08:44.000Z"
        }
    }
  • token無効時のerr値:
    {
        "name": "UnauthorizedError",
        "message": "invalid signature",
        "code": "invalid_token",
        "status": 401,
        "inner": {
            "name": "JsonWebTokenError",
            "message": "invalid signature"
        }
    }
  • クライアントtokenに戻るインターフェースを定義します.
    var jwt = require('jsonwebtoken');
    
    //      token            
    app.get('/getToken', function (req, res) {
        res.json({
            result: 'ok',
            token: jwt.sign({
                name: "BinMaing",
                data: "============="
            }, secretOrPrivateKey, {
                    expiresIn: 60 * 1
                })
        })
    });
    
    
    tokenを持って/getDataインターフェースにアクセスする.
    //         , token     authorization   header ,
    //      Bearer       ,    token 。      ,      。
    app.get('/getData', function (req, res) {
                res.send(req.user)
    });
    
    戻りの結果を表示:
    {
        "name": "BinMaing",
        "data": "=============",
        "iat": 1501814188,
        "exp": 1501814248
    }
    後続
    クライアントはtokenの正しい姿勢を携帯します.
    authorizationというheaderに入れて、対応する値はBerrで先頭から1マス空けます.
    authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiQmluTWFpbmciLCJkYXRhIjoiPT09PT09PT09PT09PSIsImlhdCI6MTUwMTgxNDE4OCwiZXhwIjoxNTAxODE0MjQ4fQ.GoxGlc6E02W5VvqDNawaOrj3MPO-4UYeFdngKR4bVTE
    なぜtokenをこのように携帯していますか?express-jwtのソースコードの中でtokenをどうやって取得しますか?
    //1  options   token                    API         getToken     
     if (options.getToken && typeof options.getToken === 'function') {
          try {
            token = options.getToken(req);
          } catch (e) {
            return next(e);
          }
          //2  authorization   token
        } else if (req.headers && req.headers.authorization) {
          // --      -----    --------->
          var parts = req.headers.authorization.split(' '); 
          if (parts.length == 2) {
            var scheme = parts[0];
            var credentials = parts[1];
    
            if (/^Bearer$/i.test(scheme)) {
              token = credentials; // 
            } else {
              if (credentialsRequired) {
                return next(new UnauthorizedError('credentials_bad_scheme', { message: 'Format is Authorization: Bearer [token]' }));
              } else {
                return next();
              }
            }
            //3          token      
          } else {
            return next(new UnauthorizedError('credentials_bad_format', { message: 'Format is Authorization: Bearer [token]' }));
          }
        }
    express-jwtは中間部品として何をしましたか?
    全体の流れ:
    Created with Rapha l 2.10先端アクセス/get Data URL express-jwtの中間部品はtokenを持っていますか?tokenが成功したかどうかを検証します.バックグラウンド/getData論理終了yes no.
    ソースの鑑賞():
    var middleware = function(req, res, next) {
        var token;
        // 1   method  options    
        if (req.method === 'OPTIONS' && req.headers.hasOwnProperty('access-control-request-headers')) {
          var hasAuthInAccessControl = !!~req.headers['access-control-request-headers']
                                        .split(',').map(function (header) {
                                          return header.trim();
                                        }).indexOf('authorization');
    
          if (hasAuthInAccessControl) {
            return next();
          }
        }
      //2    token(        )
        if (options.getToken && typeof options.getToken === 'function') {
          try {
            token = options.getToken(req);
          } catch (e) {
            return next(e);
          }
        } else if (req.headers && req.headers.authorization) {
          var parts = req.headers.authorization.split(' ');
          if (parts.length == 2) {
            var scheme = parts[0];
            var credentials = parts[1];
    
            if (/^Bearer$/i.test(scheme)) {
              token = credentials;
            } else {
              if (credentialsRequired) {
                return next(new UnauthorizedError('credentials_bad_scheme', { message: 'Format is Authorization: Bearer [token]' }));
              } else {
                return next();
              }
            }
          } else {
            return next(new UnauthorizedError('credentials_bad_format', { message: 'Format is Authorization: Bearer [token]' }));
          }
        }
    
        if (!token) {
          if (credentialsRequired) {
            return next(new UnauthorizedError('credentials_required', { message: 'No authorization token was found' }));
          } else {
            return next();
          }
        }
    
     // 3    token
        var dtoken;
        try {
          dtoken = jwt.decode(token, { complete: true }) || {};
        } catch (err) {
          return next(new UnauthorizedError('invalid_token', err));
        }
    
    // 4         
        async.waterfall([
         //        secret
          function getSecret(callback){
            var arity = secretCallback.length;
            if (arity == 4) {
              secretCallback(req, dtoken.header, dtoken.payload, callback);
            } else { // arity == 3
              secretCallback(req, dtoken.payload, callback);
            }
          },
          //  secret  token                      jsonwebtoken  token    
          function verifyToken(secret, callback) {
            jwt.verify(token, secret, options, function(err, decoded) {
              if (err) {
                callback(new UnauthorizedError('invalid_token', err));
              } else {
                callback(null, decoded);
              }
            });
          },
          //   token            express-jwt   
          function checkRevoked(decoded, callback) {
            isRevokedCallback(req, dtoken.payload, function (err, revoked) {
              if (err) {
                callback(err);
              }
              else if (revoked) {
                callback(new UnauthorizedError('revoked_token', {message: 'The token has been revoked.'}));
              } else {
                callback(null, decoded);
              }
            });
          }
    //             
        ], function (err, result){
          if (err) { return next(err); }  //           
          if (_resultProperty) {
            set(res, _resultProperty, result);
          } else {
            set(req, _requestProperty, result);
          }
          next();  //             url       
        });
      };
    express-jwtとjsonwebtoken
    express-jwtはjsonwebtokenをパッケージ化しています.検証戦略においては多くの拡張がなされています.具体的な拡張はここをご覧ください.検証戦略が簡単であれば、Jsonwebtokenを使えば十分です.以下のような事例があります.
    //             
    app.use(function(req, res, next) {
    //      token  api
        if (req.originalUrl.indexOf('/getToken') >= 0) {
            return next();
        }
    //    token api      
         var token = rq.body.token || rq.query.token || rq.headers["x-access-token"];
        jwt.verify(token, "secretOrPrivateKey", function(err, decoded) {
            if (err) {
                //       
                res.send({
                    success: false,
                    message: 'Failed to authenticate token. Make sure to include the ' +
                        'token returned from /users call in the authorization header ' +
                        ' as a Bearer token'
                });
                return;
            } else {
                //        (       token    )
                req.username = decoded.username;
                req.orgname = decoded.orgName;
                logger.debug(util.format('Decoded from JWT token: username - %s, orgname - %s', decoded.username, decoded.orgName));
                //      
                return next();
            }
        });
    });