一歩一歩、ノードを設定するガイドです.パスポートJWTとのJS API



認証と認証はアプリケーションの大部分です.保護やチェックなしにAPIルートがあるたびに、アプリケーションは簡単にハッカーのターゲットになることができます.だから私たちは安全なトークンを必要とするのです — the JSON Web Token (JWT) .

UNT JWTの基礎


私はあまり深くJWTに行くつもりはないが、ここですべての基本です.

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.


JSONのWebトークンをエンコードし、ユーザーの情報をデコードします.彼らは認可と情報交換に使用されます.
三つの部分から成る — ヘッダー、ペイロード、および署名 — ドットで区切られた. ) このように:xxxxx.yyyyy.zzzzzJSONウェブトークンについてもっと読むhere .

始める前に


お使いのコンピュータが既に持っていると仮定しますnpm そして、これをチェックしないならば、Postmanでテストしてください.
ここではcode 場合は、プロセスとのトラブルを持ってトリヴィンのslack あなたが質問をする必要があるならば.

サーバの設定


独自のサーバーを使用する場合は、この手順をスキップします.
あなたがプロジェクトを持っていないならば、我々は使用しますTrivin プロジェクトテンプレートを設定するにはこの記事では、簡単なノードサーバーを作成するために使用します.
$ npm i trivin -g
$ trivin server simple-node-server -g -i
これはa simple but well-structured node-server , gitを初期化し、プロジェクトの依存関係をすべてインストールします.

インストール


$ npm i passport passport-jwt winston cors express-validator jsonwebtoken

セットアップファイルのサポート


$ mkdir store/ 
$ touch store/passport.js store/config.js store/utils.js controller/constant.js

定数。js

  • 最初に、私は本当に定数で行うように何かです.jsファイル.多くのストリングを書く代わりに、私はストリングのために変数をつくります.
  • 許可するTextEditor 自動的に私のために完了し、文字列のtyposを減らす.
  • これらを加えるconstant.js ファイル
  • export const EMAIL_IS_EMPTY = 'EMAIL_IS_EMPTY';
    export const PASSWORD_IS_EMPTY = 'PASSWORD_IS_EMPTY';
    export const PASSWORD_LENGTH_MUST_BE_MORE_THAN_8 =
      'PASSWORD_LENGTH_MUST_BE_MORE_THAN_8';
    export const WRONG_PASSWORD = 'WRONG_PASSWORD';
    export const SOME_THING_WENT_WRONG = 'SOME_THING_WENT_WRONG';
    export const USER_EXISTS_ALREADY = 'USER_EXISTS_ALREADY';
    export const USER_DOES_NOT_EXIST = 'USER_DOES_NOT_EXIST';
    export const TOKEN_IS_EMPTY = 'TOKEN_IS_EMPTY';
    export const EMAIL_IS_IN_WRONG_FORMAT = 'EMAIL_IS_IN_WRONG_FORMAT';
    

    Utilsjs

  • プロジェクト全体で使用されるすべての機能と妥当性検査を格納するファイル.
  • これは、APIコントローラのコードをはるかにクリーナーファイルです.
  • import sha256 from 'sha256';
    import { check } from 'express-validator';
    import {
      PASSWORD_IS_EMPTY,
      PASSWORD_LENGTH_MUST_BE_MORE_THAN_8,
      EMAIL_IS_EMPTY,
      EMAIL_IS_IN_WRONG_FORMAT,
    } from './constant';
    export const generateHashedPassword = password => sha256(password);
    export function generateServerErrorCode(res, code, fullError, msg, location = 'server') {
      const errors = {};
      errors[location] = {
        fullError,
        msg,
      };
    return res.status(code).json({
        code,
        fullError,
        errors,
      });
    }
    // ================================
    // Validation:
    // Handle all validation check for the server
    // ================================
    export const registerValidation = [
      check('email')
        .exists()
        .withMessage(EMAIL_IS_EMPTY)
        .isEmail()
        .withMessage(EMAIL_IS_IN_WRONG_FORMAT),
      check('password')
        .exists()
        .withMessage(PASSWORD_IS_EMPTY)
        .isLength({ min: 8 })
        .withMessage(PASSWORD_LENGTH_MUST_BE_MORE_THAN_8),
    ];
    export const loginValidation = [
      check('email')
        .exists()
        .withMessage(EMAIL_IS_EMPTY)
        .isEmail()
        .withMessage(EMAIL_IS_IN_WRONG_FORMAT),
      check('password')
        .exists()
        .withMessage(PASSWORD_IS_EMPTY)
        .isLength({ min: 8 })
        .withMessage(PASSWORD_LENGTH_MUST_BE_MORE_THAN_8),
    ];
    

    パスポート。jsセットアップ

  • ノード.認証を支援するJSライブラリ.
  • これを加えるstore/passport.js :
  • import { Strategy, ExtractJwt } from 'passport-jwt';
    import { config, underscoreId } from './config';
    import { User } from '../database/models';
    
    export const applyPassportStrategy = passport => {
      const options = {};
      options.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
      options.secretOrKey = config.passport.secret;
      passport.use(
        new Strategy(options, (payload, done) => {
          User.findOne({ email: payload.email }, (err, user) => {
            if (err) return done(err, false);
            if (user) {
              return done(null, {
                email: user.email,
                _id: user[underscoreId]
              });
            }
            return done(null, false);
          });
        })
      );
    };
    
  • store/config.js 私はすべてのアプリケーションの私の構成を維持する場所です:
  • export const config = {
      passport: {
        secret: '<Add_Your_Own_Secret_Key>',
        expiresIn: 10000,
      },
      env: {
        port: 8080,
        mongoDBUri: 'mongodb://localhost/test',
        mongoHostName: process.env.ENV === 'prod' ? 'mongodbAtlas' : 'localhost',
      },
    };
    export const underscoreId = '_id';
    
    変更するapp.js パスポートで使用するには、次の手順に従います.
    import express from 'express';
    import logger from 'winston';
    import bodyParser from 'body-parser';
    import cors from 'cors';
    
    import passport from 'passport';
    import mongoose from 'mongoose';
    
    import { config } from './store/config';
    import { applyPassportStrategy } from './store/passport';
    import { userController } from './controller';
    
    const app = express();
    
    // Set up CORS
    app.use(cors());
    
    // Apply strategy to passport
    applyPassportStrategy(passport);
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    
    // API Route
    app.use('/', userController);
    
    /**
     * Get port from environment and store in Express.
     */
    const { port, mongoDBUri, mongoHostName } = config.env;
    app.listen(port, () => {
      logger.info(`Started successfully server at port ${port}`);
      mongoose
        .connect(mongoDBUri, { useNewUrlParser: true, useUnifiedTopology: true })
        .then(() => {
          logger.info(`Conneted to mongoDB at ${mongoHostName}`);
        });
    });
    

    実行あなたの


    $ npm start
    
    今行きましょうuser.controller.js 適用によってpassport-jwt APIに.

    パスポートJWTを登録/ログインAPIに適用します



    イメージソース:dotnetトリック.コム
    import express from 'express';
    import jwt from 'jsonwebtoken';
    
    import { validationResult } from 'express-validator';
    import { config } from '../store/config';
    
    import {
      generateHashedPassword,
      generateServerErrorCode,
      registerValidation,
      loginValidation,
    } from '../store/utils';
    
    import {
      SOME_THING_WENT_WRONG,
      USER_EXISTS_ALREADY,
      WRONG_PASSWORD,
      USER_DOES_NOT_EXIST,
    } from '../store/constant';
    
    import { User } from '../database/models';
    
    const userController = express.Router();
    
    const createUser = (email, password) => {
      const data = {
        email,
        hashedPassword: generateHashedPassword(password),
      };
      return new User(data).save();
    }
    
    /**
     * GET/
     * retrieve and display all Users in the User Model
     */
    userController.get('/', (req, res) => {
      User.find({}, (err, result) => {
        res.status(200).json({ data: result });
      });
    });
    
    /**
     * POST/
     * Register a user
     */
    userController.post('/register', registerValidation, async (req, res) => {
      const errorsAfterValidation = validationResult(req);
      if (!errorsAfterValidation.isEmpty()) {
        return res.status(400).json({
          code: 400,
          errors: errorsAfterValidation.mapped(),
        });
      } 
        try {
          const { email, password } = req.body;
          const user = await User.findOne({ email });
    
          if (!user) {
            await createUser(email, password);
    
            // Sign token
            const newUser = await User.findOne({ email });
            const token = jwt.sign({ email }, config.passport.secret, {
              expiresIn: 10000000,
            });
            const userToReturn = { ...newUser.toJSON(), ...{ token } };
    
            delete userToReturn.hashedPassword;
    
            res.status(200).json(userToReturn);
          } else {
            generateServerErrorCode(res, 403, 'register email error', USER_EXISTS_ALREADY, 'email');
          }
        } catch (e) {
          generateServerErrorCode(res, 500, e, SOME_THING_WENT_WRONG);
        }
    });
    /**
     * POST/
     * Login a user
     */
    userController.post('/login', loginValidation, (req, res) => {
      const errorsAfterValidation = validationResult(req);
      if (!errorsAfterValidation.isEmpty()) {
        return res.status(400).json({
          code: 400,
          errors: errorsAfterValidation.mapped(),
        });
      } 
          const { email, password } = req.body;
          const user = await User.findOne({ email });
          if (user && user.email) {
            const isPasswordMatched = user.comparePassword(password);
            if (isPasswordMatched) {
              // Sign token
              const token = jwt.sign({ email }, config.passport.secret,         
              {
                expiresIn: 1000000,
              });
              const userToReturn = { ...user.toJSON(), ...{ token } };
              delete userToReturn.hashedPassword;
              res.status(200).json(userToReturn);
            } else {
              generateServerErrorCode(res, 403, 'login password error', WRONG_PASSWORD, 'password');
            }
          } else {
            generateServerErrorCode(res, 404, 'login email error', USER_DOES_NOT_EXIST, 'email');
          }
    });
    export default userController;
    
  • ユーザーのメールとハッシュのパスワードを使用する代わりに、クライアントとサーバー間の通信中に確保できない場合があります.
  • 認証のためにJWTトークンを使用します.このように、我々はパスワードとパスワードのセキュリティを確保することができます暗号化する.
  • テスト

  • この時点で、あなたはPostmanを使う方法を知っていると仮定します.
  • 使用するPOST/ メソッドと入力localhost:8080/register and localhost:8080/login .
  • レジスタAPIをテストした後、以下のような結果を得ることができます.あなたのクリップボードにトークンをコピーします.

  • register api成功したトークンとユーザのメールを返します.

    認可


    ログインするユーザーが必要な特定のリンクに移動したい場合は、見てみましょう.それから、あなたは単にAPIで承認を加えることができます.
    例を見てみましょう.
  • インuser.controller.js , シンプルに含める'/' すべてのユーザのリストを取得するAPI — しかし、私はユーザとしてログインしない限り、すべてのユーザーを取得したくありません.
  • もう一つの例はFacebookです.場合は、ニュースフィードに移動し、すべての記事を取得する場合は、ログインする必要があります.
  • JWTトークンなしでセキュアされたAPIルートに移動するときの例を示します.

  • PHP APIに接続されていないJWTの例

    パスポートでの認可


    これらのハイライトをあなたに加えてくださいuser.controller.js :
    import express from 'express';
    import jwt from 'jsonwebtoken';
    import passport from 'passport';
    import { validationResult } from 'express-validator';
    ...
    /**
     * GET/
     * retrieve and display all Users in the User Model
     */
    userController.get(
      '/',
      **passport.authenticate('jwt', { session: false }),**
      (req, res) => {
        User.find({}, (err, result) => {
          res.status(200).json({ data: result });
        });
      }
    );
    ...
    export default userController;
    
    さて、PostmanでAPIをテストします.「承認」をクリックして、タイプ「Bearerトークン」を選んでください次にトークンをトークンフィールドにペーストして実行します.

    JWTを使用すると、すべてのユーザーを取得することができます

    よくできた!


    あなたは今、APIを使用する前にログインするユーザーを必要とする他のすべてのルートを承認し、安全にすることができます.
  • フォローアップしてくださいGithub | |