![](https://habrastorage.org/webt/59/ed/d2/59edd235bdb46415116934.jpeg)
これらの資料は、JavaScriptに精通しており、Node.js、npm、およびMongoDBの基本を理解しており、Node-Vue-MongoDBバンドルおよび関連技術を学びたい読者を対象としています。 アプリケーションをゼロから作成するので、お気に入りのコードエディターを用意してください。 プロジェクトを複雑にしないために、私たちはVuexを使用せず、二次的なことに気を取られることなく、最も重要なことに集中しようとします。
この資料の著者であるブラジルの開発者は、彼はJavaScriptの第一人者とはほど遠いが、新しい知識を求めて、彼が見つけたものを他の人と共有する準備ができていると言います。
ここでは、次の問題を検討します。
- プロジェクト構造の編成。
- 使用されるライブラリの依存関係のインストールと説明。
- MongoDBでの作業とMongooseモデルの作成。
- アプリケーションAPIメソッドの開発。
- エクスプレスルートの準備。
- Passport.jsを使用したJWT認証の構成。
- Postmanを使用してプロジェクトをテストします。
私たちが取り組んでいるプロジェクトのコードは、 GitHubにあります。
プロジェクト構造と依存関係のインストール
まず、プロジェクトのフォルダー構造を作成します。これは、作業の最初の段階で次のようになります。
![](https://habrastorage.org/getpro/habr/post_images/cf3/ba7/081/cf3ba70816b467ed881672b086c67911.png)
APIフォルダー構造
マテリアルを進めるにつれて、この構造を大幅に拡張します。
次に、いくつかの依存関係をインストールする必要があります。 これを行うには、プロジェクトのルートフォルダー(ここでは
focus-budget-manager
)に移動し、
npm init
コマンドで以前に
package.json
して、次のコマンドを実行します。
npm i --save express body-parser mongoose consign cors bcrypt jsonwebtoken morgan passport passport-jwt module-alias
これらの依存関係とプロジェクトでの役割の一部を検討してください。
- エクスプレス これはNode.jsのフレームワークであり、APIの開発を容易にするために使用します。
- ボディパーサー。 このパッケージは、Node.jsのクエリ本文パーサーです。 受信リクエストの本文をハンドラーに渡す前に解析するのに役立ちます。その結果、
req.body
プロパティを使用してそれらを処理できます。
- マングース。 これは、非同期環境で動作するように設計されたMongoDBのオブジェクトモデリングツールです。
- 委託。 このパッケージは補助であり、使用する必要はありません。 起動スクリプトを整理するように設計されています。
- CORS。 このパッケージは、CORSをアクティブにするために使用できるConnect / Expressヘルパーツールです。
- Bcrypt。 このパッケージを使用して、暗号化の「塩」とハッシュを生成します。
- モーガン これは、HTTP要求を記録するように設計されたNode.jsのヘルパーです。
- モジュールのエイリアス。 このパッケージを使用すると、フォルダーのエイリアスを作成し、Node.jsに独自のモジュールパスを登録できます。
パッケージをインストールした後、Gitを使用する予定がある場合は、プロジェクトのルートフォルダーに
.gitignore
ファイルを作成します。 以下を記述します:
/node_modules/
準備作業が完了したので、プログラミングを始めます。
ファイルBudgetManagerAPI / config / index.js
BudgetManagerAPI/config
index.js
BudgetManagerAPI/config
ファイルを作成し、次のコードを追加します。
module.exports = { secret: 'budgetsecret', session: { session: false }, database: 'mongodb://127.0.0.1:27017/budgetmanager' }
このファイルには、データベース接続パラメーターと、JWTトークンの作成に使用する秘密鍵が含まれています。
これは、ローカルMongoDBサーバーで動作することになっています。 同時に、行
127.0.0.1:27017
localhost
を使用できます。 必要に応じて、たとえばMLabsを使用して作成されたMongoDBクラウドデータベースを操作できます。
ファイルBudgetManagerAPI / app / models / user.js
JWT認証に使用される
User
モデルを作成し
User
。 これを行うには、
BudgetManagerAPI/app
フォルダーに移動し、その中に
models
ディレクトリーを作成し、その中に
user.js
ファイルを
user.js
ます。 ファイルの先頭で、依存関係を接続します。
const mongoose = require('mongoose'), bcrypt = require('bcrypt');
ここでは、
User
モデルを作成するために
mongoose
パッケージが必要です
bcrypt
パッケージツールは、ユーザーパスワードをハッシュするために使用されます。
その後、同じファイルに次を追加します。
const Schema = mongoose.Schema({ username: { type: String, unique: true, required: true }, password: { type: String, required: true }, clients: [{}] });
このコードは、
User
データスキーマを作成するためのものです。 この説明により、次のデータがシステムのユーザーに割り当てられます。
- ユーザー名
- パスワード
- クライアントのリスト(
clients
)。
クライアント情報には、電子メールアドレス(電子メール)、名前(名前)、電話(電話)、および財務書類(予算)が含まれます。 財務ドキュメントには、状態、タイトル、アイテム、価格などのデータが含まれます。
user.js
ファイルを引き続き使用し、次のコードを追加します。
// - Schema.pre('save', function (next) { const user = this; if (this.isModified('password') || this.isNew) { bcrypt.genSalt(10, (error, salt) => { if (error) return next(error); bcrypt.hash(user.password, salt, (error, hash) => { if (error) return next(error); user.password = hash; next(); }); }); } else { return next(); } });
この関数では、ユーザーパスワードの暗号化ソルトとハッシュを生成します。
この関数のコードに従って、パスワードを比較し、システムへのユーザーアクセスの有効性を確認する関数を追加します。
Schema.methods.comparePassword = function (password, callback) { bcrypt.compare(password, this.password, (error, matches) => { if (error) return callback(error); callback(null, matches); }); };
次に、ファイルの最後で、
User
モデルを作成し
User
。
mongoose.model('User', Schema);
ファイルBudgetManagerAPI / config / passport.js
User
モデルの準備ができたら、
passport.js
ファイルを
BudgetManagerAPI/config
フォルダーに作成します。 依存関係接続を使用してこのファイルの作業を始めましょう。
const PassportJWT = require('passport-jwt'), ExtractJWT = PassportJWT.ExtractJwt, Strategy = PassportJWT.Strategy, config = require('./index.js'), models = require('@BudgetManager/app/setup');
User
モデルを
passport-jwt
は
passport-jwt
パッケージが必要です
passport-jwt
は認証を整理するためのものです。
次に、このファイルに次を追加します。
module.exports = (passport) => { const User = models.User; const parameters = { secretOrKey: config.secret, jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken() }; passport.use(new Strategy(parameters, (payload, done) => { User.findOne({ id: payload.id }, (error, user) => { if (error) return done(error, false); if (user) done(null, user); else done(null, false); }); })); }
ここでは、
User
モデルのインスタンスを作成し、クライアントから受信したJWTトークンを検索してユーザーを見つけます。
ファイルBudgetManagerAPI / config / database.js
BudgetManagerAPI/config
フォルダーで、
database.js
操作を担当する
database.js
ファイルを作成します。 このファイルに次を追加します。
module.exports = (mongoose, config) => { const database = mongoose.connection; mongoose.Promise = Promise; mongoose.connect(config.database, { useMongoClient: true, promiseLibrary: global.Promise }); database.on('error', error => console.log(`Connection to BudgetManager database failed: ${error}`)); database.on('connected', () => console.log('Connected to BudgetManager database')); database.on('disconnected', () => console.log('Disconnected from BudgetManager database')); process.on('SIGINT', () => { database.close(() => { console.log('BudgetManager terminated, connection closed'); process.exit(0); }) }); };
ここでは、最初に
mongoose
を標準の
Promise
オブジェクトの使用に切り替えました。 これを行わないと、コンソールに警告が表示される場合があります。 次に、標準の
mongoose
接続を作成しました。
サーバーのセットアップ、サービス/ index.jsファイル
いくつかの補助サブシステムを処理した後、サーバーの構成を開始します。
services
フォルダーに移動し、既にその中にある
index.js
ファイルを開きます。 以下を追加します。
require('module-alias/register'); const http = require('http'), BudgetManagerAPI = require('@BudgetManagerAPI'), BudgetManagerServer = http.Server(BudgetManagerAPI), BudgetManagerPORT = process.env.PORT || 3001, LOCAL = '0.0.0.0'; BudgetManagerServer.listen(BudgetManagerPORT, LOCAL, () => console.log(`BudgetManagerAPI running on ${BudgetManagerPORT}`));
後で設定する
module_alias
を接続することから始めます(この手順はオプションですが、このアプローチはコードをよりきれいにするのに役立ちます)。
module_alias
代わりに
@BudgetManagerAPI
パッケージを使用しない場合は、.
module_alias
/
@BudgetManagerAPI
/
@BudgetManagerAPI
を記述する必要があり
./services/BudgetManagerAPI/config
。
サーバーを起動するには、プロジェクトのルートディレクトリに移動し、使用するコマンドラインインタープリターに
node services
コマンドを入力し
node services
。
ファイルBudgetManagerAPI / config / app.js
BudgetManagerAPI/config
ディレクトリで、
app.js
ファイルを作成します。 開始するには、依存関係を接続しましょう。
const express = require('express'), app = express(), bodyParser = require('body-parser'), mongoose = require('mongoose'), morgan = require('morgan'), consign = require('consign'), cors = require('cors'), passport = require('passport'), passportConfig = require('./passport')(passport), jwt = require('jsonwebtoken'), config = require('./index.js'), database = require('./database')(mongoose, config);
passportConfig = require('./passport')(passport)
は、
passport
の構成ファイルをインポートし、
passport.js
には次のコマンドがあるため、引数として
passport
を渡します。
![](https://habrastorage.org/getpro/habr/post_images/c7e/80a/495/c7e80a4952c9be32dd430b05dfab8a15.png)
このアプローチのおかげで、
passport.js
ファイル内の
passport.js
を接続することなく操作できます。
次に、
app.js
ファイルで、パッケージの操作を開始し、秘密キーを設定します。
app.use(express.static('.')); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(morgan('dev')); app.use(cors()); app.use(passport.initialize()); app.set('budgetsecret', config.secret);
または、
cors
パッケージを使用する代わりに、次のことを実行できます。
app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); });
package.jsonの構成
プロジェクトのルートディレクトリに移動し、
package.json
を開いて、
dependencies
ブロックの直前に以下を追加します。
"homepage": "https://github.com/gdomaradzki/focus-gestor-orcamentos#readme", "_moduleAliases": { "@root": ".", "@BudgetManager": "./services/BudgetManagerAPI", "@BudgetManagerModels":"./services/BudgetManagerAPI/app/models", "@BudgetManagerAPI":"./services/BudgetManagerAPI/config/app.js", "@config": "./services/BudgetManagerAPI/config/index.js" }, "dependencies": {
dependencies
ブロックは既にファイル内にあるため、
_moduleAliases
homepage
と
_moduleAliases
ブロックを追加するだけでよいことに注意してください。
これらの変更により、
@root
エイリアスを使用してプロジェクトのルートディレクトリにアクセスし、
@root
エイリアスを使用して
index.js
構成ファイルにアクセスできるようになります。
ファイルBudgetManagerAPI / app / setup / index.js
エイリアスを設定し
BudgetManagerAPI/app
、
BudgetManagerAPI/app
フォルダーに移動して、新しい
setup
フォルダーを作成し、その中に
index.js
ファイルを作成します。 以下を追加します。
const mongoose = require('mongoose'), UserModel = require('@BudgetManagerModels/user');; const models = { User: mongoose.model('User') } module.exports = models;
他の何かがアプリケーションにロードされる前にモデルのロードを確実にするためにこれを行います。
ファイルBudgetManagerAPI / app / api / auth.js
現在、APIメソッドのいくつかを作成し始めています。
BudgetManagerAPI/app
フォルダーに移動して、その中に
api
ディレクトリーを作成し、その中に
auth.js
ファイルを
auth.js
ます。 私たちはそれに以下を書きます:
const mongoose = require('mongoose'), jwt = require('jsonwebtoken'), config = require('@config');
module_alias
モジュールのおかげで、コードクリーナーを作成したことに注意してください。 そうでなければ、私は次のようなものを書かなければなりません:
config = require('./../../config);
ここで、パッケージを接続した後、同じファイルで次のことを行います。
const api = {}; api.login = (User) => (req, res) => { User.findOne({ username: req.body.username }, (error, user) => { if (error) throw error; if (!user) res.status(401).send({ success: false, message: 'Authentication failed. User not found.' }); else { user.comparePassword(req.body.password, (error, matches) => { if (matches && !error) { const token = jwt.sign({ user }, config.secret); res.json({ success: true, message: 'Token granted', token }); } else { res.status(401).send({ success: false, message: 'Authentication failed. Wrong password.' }); } }); } }); }
ここでは、必要なすべてのメソッドを保存する空の
api
オブジェクトを作成します。 最初に、
User
メソッドを
login
メソッドに渡します。ここでは、
User
モデルにアクセスするメソッドが必要なので、次に、
req
および
res
引数を渡します。
このメソッドは、
User
username
一致する
User
オブジェクトを検索し
username
。 ユーザー名を認識できない場合はエラーが発生し、そうでない場合はユーザーに関連付けられているパスワードとトークンを確認します。
次に、トークンを受信して解析するもう1つの
api
メソッドが必要です。
api.verify = (headers) => { if (headers && headers.authorization) { const split = headers.authorization.split(' '); if (split.length === 2) return split[1]; else return null; } else return null; }
このメソッドはヘッダーをチェックし、
Authorization
ヘッダーを取得します。 これらすべてのステップの後、最終的に
api
オブジェクトをエクスポートできます。
module.exports = api;
API Routes、BudgetManagerAPI / app / routes / auth.jsファイル
APIルートを作成しましょう。 これを行うには、
services/BudgetManagerAPI/app
フォルダーに移動し、その中に
routes
ディレクトリを作成します。ここで、次の内容の
auth.js
ファイルを作成します。
const models = require('@BudgetManager/app/setup'); module.exports = (app) => { const api = app.BudgetManagerAPI.app.api.auth; app.route('/') .get((req, res) => res.send('Budget Manager API')); app.route('/api/v1/auth') .post(api.login(models.User)); }
このモジュールに
app
オブジェクトを渡すので、ルートを設定できます。 ここで、
api
定数を設定します。これは、
api
フォルダー内の
auth.js
ファイルを操作するために使用します。 ここでは、デフォルトルート
'/'
を設定します。アクセスすると、文字列「Budget Manager API」がユーザーに渡されます。 次に、ルート
'/api/v1/auth'
を作成します(POST要求が使用される作業用)。 このルートを提供するには、
login
メソッドを使用して、
User
モデルを引数として渡します。
ファイルBudgetManagerAPI / config / app.js
次に、
BudgetManagerAPI/config
フォルダーにある
app.js
ファイルに戻り、次の行を追加します(
app.set('budgetsecret', config.secret)
ガイドラインとして指定されています。2回目にファイルに追加する必要はありません)。
app.set('budgetsecret', config.secret); consign({ cwd: 'services' }) .include('BudgetManagerAPI/app/setup') .then('BudgetManagerAPI/app/api') .then('BudgetManagerAPI/app/routes') .into(app); module.exports = app;
ここでは、他のアクションを実行する前に、
setup
フォルダーのコンテンツが読み込まれているかどうかを確認し、モデルが最初にインスタンス化されるようにします。 次に、APIメソッドをロードし、最後にルートをロードします。
ファイルBudgetManagerAPI / app / api / user.js
BudgetManagerAPI/app/api
フォルダーに
user.js
、その中に
user.js
ファイルを作成します。 次のコードを入れてください:
const mongoose = require('mongoose'); const api = {}; api.setup = (User) => (req, res) => { const admin = new User({ username: 'admin', password: 'admin', clients: [] }); admin.save(error => { if (error) throw error; console.log('Admin account was succesfully set up'); res.json({ success: true }); }) }
setup
方法では、デバッグ用の管理者アカウントを作成できます。 完成したアプリケーションでは、このアカウントはそうではありません。
次に、同じファイル内で、テスト目的で使用するメソッドを作成します。これにより、アプリケーションに登録し、認証メカニズムを確認する必要があるすべてのユーザーをリストできます。
api.index = (User, BudgetToken) => (req, res) => { const token = BudgetToken; if (token) { User.find({}, (error, users) => { if (error) throw error; res.status(200).json(users); }); } else return res.status(403).send({ success: false, message: 'Unauthorized' }); }
次に、後で必要になる
signup
メソッドを作成します。 新しいユーザーを登録するように設計されています。
api.signup = (User) => (req, res) => { if (!req.body.username || !req.body.password) res.json({ success: false, message: 'Please, pass a username and password.' }); else { const newUser = new User({ username: req.body.username, password: req.body.password, clients: [] }); newUser.save((error) => { if (error) return res.status(400).json({ success: false, message: 'Username already exists.' }); res.json({ success: true, message: 'Account created successfully' }); }) } } module.exports = api;
ここで、新しいユーザーを登録しようとするときに、
username
と
password
フィールドが
password
ているかどうかがチェックされ
password
されている場合は、有効なユーザー名が入力されると新しいユーザーが作成されます。
アプリケーションの作業のこの段階では、ユーザーと作業するためのAPIメソッドが準備できていると想定しています。
ファイルBudgetManagerAPI / app / routes / user.js
次に、
BudgetManagerAPI/app/routes
フォルダーに
user.js
ファイルを作成し、次のコードを書き込みます。
const passport = require('passport'), config = require('@config'), models = require('@BudgetManager/app/setup'); module.exports = (app) => { const api = app.BudgetManagerAPI.app.api.user; app.route('/api/v1/setup') .post(api.setup(models.User)) app.route('/api/v1/users') .get(passport.authenticate('jwt', config.session), api.index(models.User, app.get('budgetsecret'))); app.route('/api/v1/signup') .post(api.signup(models.User)); }
ここでは、認証用の
passport
ライブラリをインポートし、構成ファイルを接続してセッションパラメーターを構成し、モデルを接続するため、ユーザーがAPIエンドポイントを操作する権利を持っているかどうかを確認できます。
テスト
最初にアプリケーションサーバーとデータベースサーバーを実行して、作成したものを確認します。 つまり、アドレスhttp:// localhost:3001 /に移動すると、サーバーが実行されているターミナルウィンドウで、リクエストに関する情報(リクエストが成功したことを意味する200)が表示されます。応答。 次のようになります。
![](https://habrastorage.org/getpro/habr/post_images/441/0b1/066/4410b1066d56ec9036f851974b987b44.png)
クライアントアプリケーション、つまりブラウザは、「予算マネージャーAPI」というテキストを含む通常のページを表示する必要があります。
http:// localhost:3001 / api / v1 / authからアクセスできるルート
route
確認しましょう。
ステータスが404のGETリクエストに関するメッセージがサーバーウィンドウに表示されます(これはサーバーに接続できたが、必要なものを提供できないことを示します)および応答時間。
![](https://habrastorage.org/getpro/habr/post_images/b33/5b9/19f/b335b919fc2ed273458a4a0309377339.png)
これは、このAPIエンドポイントをPOSTリクエストにのみ使用しているためです。 GETリクエストを実行した場合、サーバーには応答するものがありません。
http:// localhost:3001 / api / v1 / usersにアクセスして 、
user
ルートを確認します 。 サーバーは、ステータス401のGETメソッドを報告します。これは、ターゲットリソースを操作するための十分な特権がないため、要求が処理されなかったことを示します。 クライアントは、テキスト「Unauthorized」を含むページを発行します。
これにより、認証システムが機能していると判断できますが、ここでは、登録フォームさえ持っていない場合、ログイン方法を確認する方法についての質問が発生します。
この問題を解決する1つの方法は、Postmanを使用することです。 通常のアプリケーションとしてダウンロードしてインストールするか、Chromeブラウザーの拡張形式を使用できます。
Postmanを使用したアプリケーションのテスト
開始するには、
setup
エンドポイントに接続して管理者アカウントを作成します。 Postmanインターフェースでは、次のようになります。
![](https://habrastorage.org/getpro/habr/post_images/6e1/a8a/226/6e1a8a226826451b254ed8855cde10f4.png)
アドレスフィールドに
http://localhost:3001/api/v1/setup
と入力し、リクエストタイプを
POST
変更して、[
Send
]ボタンをクリックします。 サーバーのJSON応答には、メッセージ
"success": true
が含まれている必要があります。
次に、管理者アカウントでログインしてみてください。
![](https://habrastorage.org/getpro/habr/post_images/d56/ce4/8c4/d56ce48c4f732e84e577fb5c6c7cc515.png)
これを行うには、エンドポイント
http://localhost:3001/api/v1/auth
へのPOSTリクエストを使用して、[
Body
]タブで同じ
admin
値で
username
と
password
キーを設定し、[
Send
]ボタンを押します。
サーバーの応答は、次の画像のようになります。
![](https://habrastorage.org/getpro/habr/post_images/cf6/a27/9fb/cf6a279fb4d7ae214e1c8966526f8054.png)
次に、システムユーザーのリストを取得します。
![](https://habrastorage.org/getpro/habr/post_images/736/8f2/87e/7368f287e115232478417f0e8b8c213d.png)
これを行うには、
token
キーの値をコピーし、GETリクエストを
http://localhost:3001/api/v1/users
して、アドレスフィールドに
http://localhost:3001/api/v1/users
と入力し、[
Headers
]タブで、
Bearer token
(
token
なく
token
以前に受信したサーバー応答からコピーされたトークンを貼り付けます)。 同じ場所で、値
application/x-www-form-urlencoded
の
Content-Type
ヘッダーを追加し、
Send
をクリックします。
応答はJSON配列である必要があります。JSON配列の場合、管理者である1人のユーザーのみに関する情報があります。
![](https://habrastorage.org/getpro/habr/post_images/05a/603/980/05a60398006d685421f2e1a09b3c307f.png)
次に、新しいユーザー登録方法
signup
確認します。
![](https://habrastorage.org/getpro/habr/post_images/68c/db5/eb5/68cdb5eb5efcb308f898667e18b976ee.png)
これを行うには、新しいタブを開き、エンドポイント
http://localhost:3001/api/v1/signup
へのPOSTリクエストを構成し、[
Body
]タブで、
x-www-form-urlencoded
スイッチを選択し、次の値とは異なる
username
と
password
キーを
password
ます
admin
をクリックし、[
Send
]
Send
クリックします。 すべてが正常に機能する場合、次の応答が表示されます。
![](https://habrastorage.org/getpro/habr/post_images/c54/fcc/fc5/c54fccfc5230ac58da6f5baa18efb22b.png)
次に、
http://localhost:3001/api/v1/users
移動した
Postman
タブに戻って
http://localhost:3001/api/v1/users
のリストを取得し、
Send
をクリックすると、管理者と新しいユーザーを表す2つのオブジェクトの配列が返されます。
![](https://habrastorage.org/getpro/habr/post_images/bed/ba4/474/bedba4474e1d250c38fb5b84300b0514.png)
まとめ
これで、このシリーズの最初のパートは終わりです。 ここでは、ゼロからNode.jsアプリケーションを作成し、簡単なJWT認証をセットアップする方法を学びました。 次のパートでは、Vue.jsを使用してアプリケーションのユーザーインターフェイスの開発を開始します。
親愛なる読者! 著者によって提案された著者認証方法は、本番環境での使用に適していると思いますか?