[解決済み】node.jsでセキュアなREST APIを実装する方法
質問
node.js、express、mongodbを使ったREST APIの企画を始めています。このAPIは、ウェブサイト(公開および非公開エリア)、そしておそらく将来のモバイルアプリのためのデータを提供します。フロントエンドはAngularJSで開発される予定です。
ここ数日、REST APIのセキュリティについていろいろと読みましたが、最終的な解決策にたどり着けません。私が理解している限りでは、基本的なセキュリティを提供するためにHTTPSを使用することです。しかし、私はそのユースケースでAPIをどのように保護することができますか?
-
Webサイト/アプリの訪問者/ユーザーのみが、Webサイト/アプリの公開領域のデータを取得することができる
-
認証され許可されたユーザーのみが、プライベートエリアのデータを取得することができます(また、ユーザーが権限を与えたデータのみ)。
今のところ、アクティブなセッションを持つユーザーのみにAPIを使用させることを考えています。ユーザーの認証にはパスポートを使用し、許可には自分自身で何かを実装する必要があります。すべてHTTPSの上にあります。
どなたかベストプラクティスや経験を教えていただけませんか?私の「アーキテクチャ」に不足があるのでしょうか?
解決方法は?
私も同じような問題を抱えています。私が構築しているウェブサイトは、携帯電話やブラウザからアクセスできるため、ユーザーがサインアップ、ログイン、いくつかの特定のタスクを実行できるようにするためのAPIが必要です。さらに、スケーラビリティをサポートする必要があり、同じコードが異なるプロセス/マシンで実行される必要があります。
ユーザーはリソースを作成することができるため (別名 POST/PUT アクション)、API を保護する必要があります。oauthを使用するか、独自のソリューションを構築することができますが、パスワードが本当に簡単に発見された場合、すべてのソリューションが破られる可能性があることに留意してください。基本的な考え方は、ユーザー名、パスワード、トークン(別名:アピトークン)を使ってユーザーを認証することです。この apitoken は次のようにして生成します。 ノードユーアイディー を使用し、パスワードをハッシュ化することができます。 pbkdf2
次に、セッションをどこかに保存する必要があります。プレーンなオブジェクトでメモリ上に保存すると、サーバを一度終了して再度起動したときに、セッションが破壊されてしまいます。また、これではスケーラブルではありません。マシン間の負荷分散のために haproxy を使用したり、単に workers を使用したりすると、 このセッションの状態はひとつのプロセスに保存されることになり、 同じユーザーが別のプロセスやマシンにリダイレクトされると、 再び認証が必要になります。そのため、セッションを共通の場所に保存しておく必要があります。これは通常、redisを使用して行われます。
ユーザーが認証されると(ユーザー名+パスワード+アピトークン)、セッション用の別のトークン、別名アセスストークンを生成します。ここでもnode-uuidを使用します。ユーザーにaccessstokenとuseridを送ります。userid(キー)とaccessstoken(値)はredisに保存され、1時間などの有効期限を持つ。
これで、ユーザーが rest api を使って何か操作をするたびに、userid と accesstoken を送信する必要があります。
ユーザーがrest apiを使ってサインアップできるようにする場合、新規ユーザーはサインアップ時にapitokenを持っていないため、admin apitokenでadminアカウントを作成し、モバイルアプリに保存する必要があります(ユーザー名+パスワード+apitokenを暗号化する)。
Webでもこのapiを使いますが、apitokensを使う必要はありません。Redisストアでexpressを使うか、上記と同じ手法でapitokenのチェックを回避してuserid+accesstokenをcookieでユーザーに返せばいいのです。
プライベートエリアがある場合、認証時にユーザー名と許可されたユーザーを比較します。また、ユーザーにロールを適用することもできます。
概要を説明します。
apitokenを使わない代替案としては、HTTPSを使用し、Authorizationヘッダでユーザ名とパスワードを送信し、ユーザ名をredisにキャッシュする方法があります。
関連
-
[解決済み] テスト
-
[解決済み】MongoDBのデータ/DBが見つからない
-
[解決済み] cURLでJSONデータをPOSTするにはどうすればよいですか?
-
[解決済み] Node.jsのプログラムにコマンドライン引数を渡すにはどうしたらいいですか?
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] Node.jsで終了する方法
-
[解決済み] Node.jsアプリケーションをデバッグするにはどうすればよいですか?
-
[解決済み] Node.js上のExpress.jsでGET(クエリ文字列)変数を取得する方法とは?
-
[解決済み] RESTアプリケーションはステートレスであることが前提である場合、セッションはどのように管理するのですか?
-
[解決済み】REST APIでのPUTメソッドとPATCHメソッドの使い分け 実生活でのシナリオ
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] リソースの読み込みに失敗しました: net::ERR_CONNECTION_REFUSED : Nodejs
-
[解決済み】Discord.js が特定のチャンネルにメッセージを送信する場合
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み】npx コマンドが見つかりません。
-
[解決済み】「npm install」と「npm rebuild」の違いとは?
-
[解決済み] ブラウザで動作しているURLで「connect ETIMEDOUT」エラーが発生する原因は何ですか?
-
[解決済み] nodejs - http.requestでresponse.writeを使用する場合、第一引数は文字列またはBufferでなければなりません。
-
[解決済み] Npmエラー - Windows NT - 解決方法
-
[解決済み] S3 Bucket に何かを送信しようとすると、AWS Missing credentials が表示される (Node.js)
-
[解決済み】RESTful 認証