web-dev-qa-db-ja.com

クライアント側のJavascriptからデータベースに直接移行しない理由はありますか?

重複の可能性:
Web「サーバーレス」アプリケーションの作成

それでは、Stack Exchangeクローンを作成して、CouchDBなどをバックエンドストアとして使用するとします。組み込みの認証とデータベースレベルの承認を使用する場合、クライアント側のJavaScriptが公的に利用可能なCouchDBサーバーに直接書き込むことを許可しない理由はありますか?これは基本的にCRUDアプリケーションであり、ビジネスロジックは「投稿者だけが投稿を編集できる」で構成されているため、クライアント側のものとデータベースの間にレイヤーを設ける必要はあまりありません。 CouchDB側で検証を使用して、誰かがガベージデータを入力していないことを確認し、ユーザーが自分の_userデータのみを読み取ることができるように権限が適切に設定されていることを確認します。レンダリングは、AngularJSのようなものによってクライアント側で行われます。本質的には、CouchDBサーバーと一連の「静的」ページを用意するだけで十分です。サーバー側の処理は一切必要なく、HTMLページを提供できるものだけが必要です。

私のデータベースを世界に向けて開くのは間違っているように見えますが、このシナリオでは、権限が適切に設定されている限り、その理由を考えることができません。 Web開発者としての私の本能に反しますが、正当な理由を考えることはできません。では、なぜこれが悪い考えなのでしょうか。

編集:ここで同様の議論があるように見えます: Web「サーバーレス」アプリケーションを書く

編集:これまでのところ素晴らしい議論です、そして私はみんなのフィードバックに感謝します!特にCouchDBとAngularJSを呼び出す代わりに、いくつかの一般的な前提を追加する必要があるように感じます。それで、それを仮定しましょう:

  • データベースは非表示のストアから直接ユーザーを認証できます
  • すべてのデータベース通信はSSLを介して行われます
  • データ検証can(しかし、多分すべきではない?)はデータベースによって処理されます
  • 管理機能以外で私たちが気にする唯一の承認は、自分の投稿の編集のみが許可されている人です
  • 誰もがすべてのデータを読み取ることができるので、問題はありません(パスワードハッシュを含む可能性のあるユーザーレコードを除く)
  • 管理機能はデータベース許可によって制限されます
  • 自分を管理者の役割に追加することはできません
  • データベースは比較的簡単に拡張できます
  • 真のビジネスロジックはほとんどありません。これは基本的なCRUDアプリです
63
Chris Smith

提案どおりに実行すると、クライアント側の言語とデータベースの間の緊密な結合が作成されます。

それは大丈夫かもしれません-記述して維持するコードが少なくて済み、理論的にはデバッグが少し速くなる/そうなるはずです。

一方、他の側面をより困難にします。これらのテクノロジーのいずれかを変更する必要がある場合は、これらのテクノロジーが密接に結合しているため、困難な状況になります。

攻撃から身を守ることは(かなり)少し難しいでしょう。クライアントが常にデータベースに適切にフォーマットされたリクエストを提示すると想定しています。これは、悪意のあるステートメントを挿入するためにクライアント側のコードをハッキングする人がいないことを想定しています。つまり、認証メカニズムを「借用」し、通常のクライアントコードをそれらのコードに置き換えます。

私はそれをお勧めしませんし、多くの人は熱心にあなたに勧めないでしょう。しかしできるできる。

48
user53019

それはおそらく素晴らしいアイデアではありません。そして、私が与えることができる最初で最も強力な理由は、データベースサーバーが設計されていないパブリックWebサーバーではないということです。 逆に、従来の知識では、データベースをファイアウォールの背後に隠す必要があるとしています。

裏付けとなる証拠が必要な場合は、懸念事項がたくさんあります。すべてを克服することはできませんが、考えることはたくさんあります。順不同で、ここにいくつかあります:

  • クエリを直接送信しているため、クエリのサニタイズを実行できません。
  • データベースの権限は、Webサーバーやアプリケーションの権限とは異なる働きをする傾向があります。 Webサーバーとアプリケーションフレームワークは何もないところから始まり、個々のリソース、エンドポイント、アクションを明示的に作成して公開する必要があります。一方、データベースは、高レベルでロールを付与するように要求します。
  • Webサーバーのワークロードを維持するために十分に最適化されていない可能性があります。接続プーリングのメリットはありません。
  • より人気のあるWebサーバーはたくさんに分割されています。そして、彼らは多くのセキュリティパッチを受け取りました。 DBMSは基本的にファイアウォールの背後に隠れるように設計されているため、パブリックWebで直面する可能性のある潜在的な脅威のごく一部でもテストされていません。
  • プライベートデータを保護するには、データベースのクエリ言語を使用する必要があります。 DBMSによっては、それが困難な場合があります。
  • あなたは必要がありますデータベースのクエリ言語を使用して大規模なデータセットをフィルタリングします。しかし、より複雑なビジネスルールでは負担になる可能性があるもの。
  • サードパーティライブラリのサポートが制限されるか、サポートされません。
  • 遭遇する多くの問題に対する非常に限定された(潜在的にゼロの)コミュニティサポート。

...そして、他の懸念があると確信しています。そして、これらの懸念のすべてではないにしても、ほとんどの解決策があると確信しています。しかし、あなたが始めるためのリストがあります!

36
svidgen

私が想像できる最高の単一の理由は、この方法が関係者によって直接サポートまたは推奨されていないためです。

ブラウザーベンダー、EcmaScript標準、データベースシステム開発者、ネットワーキング機器会社、ホスティング/インフラストラクチャアーキテクト、およびセキュリティスペシャリストは、提案されたユースケースを積極的にサポートしていません(あるいは検討しさえしていません)。関係するシステムがこれをサポートするように設計されていなくても、提案された方法ではこれらのエンティティすべて(およびそれ以上)がアプリケーションに適切に機能する必要があるため、これは問題です。

不可能だと言っているのではありません。これは「ホイールを再発明する」というよりは、ブラウザベースのクライアントとサーバーの相互作用を再発明することに似ています。

せいぜい、システムを最も基本的な可能なレベルで機能させるために、多くの作業を行うことになります。最近の一般的なデータベースはRESTfulではなく、HTTP経由で動作するように構築されていないため、独自のWebSocketベースの(私は推測する)クライアントドライバーを構築します。

すべてを技術的に機能させても、最新のアーキテクチャの最も強力な機能の多くを放棄することになります。あなたは深く防御することはできません-ほとんどのウェブサイトのハッキングの試みの主要なターゲットに誰でも簡単に直接接続できます。しかし、あなたが提案するシナリオは、それよりはるかに悪いです。

提案されたモデルはサーバーを公開するだけではなく、有効な接続文字列を公開します。攻撃者はサーバーにpingするだけではなく、積極的にログインしてコマンドを送ることができます。データアクセスを制限できるとしても、サービス拒否シナリオとその同類から保護するためにDBMSシステムに十分なツールがあることは知りません。 TSQLのようなSQLの拡張バージョンで作業する場合、効果的に無限に実行される爆弾を生成するのは簡単なことです(デカルト積を生成するためのいくつかの無制限の結合と、永続的に実行され、重い作業を行うSELECTがあります)。 。 SQLのほとんどの機能を無効にし、JOINを使用した基本的なSELECTクエリを削除し、ストアドプロシージャの呼び出しのみを許可する必要があると思いますか?あなたがそれをすることができるかどうかさえ知りません、私は試すように頼まれたことはありません。それは良く聞こえません。

データベースのスケーラビリティは、大規模での作業において最も困難な問題の1つになる傾向がありますが、複数のHTTPサーバー(特に静的またはキャッシュされたページ)をスケールアウトすることは、最も簡単な部分の1つです。あなたの提案は、基本的にサーバー側のアクティビティの100%を担当することで、データベースがより多くの作業を行うようにします。それはそれだけでキラー欠陥です。作業をクライアントに移動することで得られるものは、データベースにさらに作業を移動することで失われます。

最後に、提案した内容の核心は新しいものではなく、実際には数十年前にさかのぼります。このモデルは「ファットデータベース」モデルと呼ばれ、基本的には、ほとんどのサーバー側ロジックを提案どおりデータベースに移動しました。モデルが大衆インターネットの道端に行ったのには多くの理由があり、自分でその歴史をさらに詳しく調べることはおそらく有益です。また、システムに絶えず攻撃しているはずのない内部(既知の)ユーザーを選択するようにアクセスが制御されるため、完全に信頼されていないユーザーがシステムにログインしてコマンドを実行できることについてはほとんど考慮されていません。

実際のところ、データベースシステムはファイルを提供しないため、ファイルを提供するにはHTTPサーバーが必要です。同時に、(Nodejsなどの)シンサーバーモデルを使用してRESTfulインターフェースをデータベースに公開することで、提案するすべてを取得できます。これは理由で人気があります-機能し、データベースを保護レイヤーの背後に隠し、非常にスケーラブルでありながら、データベースを必要に応じてシックまたはシンに構築できます。

16
BrianH

これは基本的にCRUDアプリケーションであり、ビジネスロジックは「投稿者だけが投稿を編集できる」で構成されているため、クライアント側のものとデータベースの間にレイヤーを設ける必要はあまりありません。 CouchDB側で検証を使用して、誰かがガベージデータを入力していないことを確認し、ユーザーが自分の_userデータのみを読み取ることができるように権限が適切に設定されていることを確認します。

まあ、あなたのauthorization(セキュリティ上の懸念)とロジックの検証をデータベースから離れた場所に置く懸念の分離を提供するをソフトウェアシステムに配置します。したがって、システムの機能にブレーキをかけるリスクが少ない状態で、論理コードブロックをテスト、維持、スケーリング、再利用できます。

クライアント入力がデータベースと直接通信する機能を提供すると、非常に大きなデータを台無しにする可能性があります。

これはまた、回避/削除タイトカップリングにより、ソフトウェアシステムの保守性とSOLIDが向上することも意味します。

8
Yusubov

ユーザーがデータベースを直接操作することは、私にとって本当に危険に思われます。

CouchDBの認証メカニズムは本当に洗練されているため、ユーザーの読み取りおよび書き込みアクセスを、読み取りおよび書き込みが想定されているデータにのみ分離できます(ドキュメントごと、場合によってはドキュメントフィールドごとのアクセスについても話しています)。特権はここに)?複数のユーザーが共有する「共通の」データはどうですか?これはアプリケーション設計にまったく存在しませんか?

ユーザーがデータをなんらかの方法で変更できるようにしますか?たとえば、XSSインジェクションはどうですか?それらがデータベースに入る前にそれらをフィルタリングするサーバー層がある方がいいのではないでしょうか?

6
Philipp

いくつかの理由がありますが、もう1つは、将来性があることです。遅かれ早かれ、アプリケーションが進化するにつれて、クライアント側のJSで、またはデータベースのストアドプロシージャとして簡単または安全に実現できない要件が提示されます。

たとえば、すべての新規登録が有効になるには、CAPTCHA検証が必要であると言われました。これは、ほとんどすべての最新のWebアプリケーションフレームワークで非常に簡単です。登録フォームで reCAPTCHA をたたき、reCAPTCHAの応答トークンをバックエンドに渡し、バックエンドに数行のコードを追加して、GoogleのAPIでトークンの有効性を確認します(または、さらに他の誰かがあなたのためにそれを行うために書いたライブラリ。

2層システムを使用していて、すべてのサーバー側ロジックをデータベースに依存している場合、トークンをどのように検証しますか?はい、DBMSによっては、シェルを呼び出して適切な引数でcurlを呼び出すストアドプロシージャを作成することが理論的に可能であると思います。これもほぼ間違いなく恐ろしい考えです。入力のフィルタリングとセキュリティの脆弱性からの保護はひどいものです。あなたはエラー処理とタイムアウトを扱う混乱を持っているでしょう。自分で応答を解析する必要があります。言うまでもなく、DBMSはこれを行うことを意図していないので、パフォーマンス、安定性、スレッドセーフなどが問題になることを考える理由はありません。たとえば、Postgresのこれらの問題のいくつかについて説明している this thread を参照してください。

そしてそれは、フォームに単純なキャプチャを1つ追加することに関する問題です。 SMS検証、または非アクティブなユーザーにメールでアプリについて通知するバックグラウンドジョブを追加する場合、またはファイルアップロード機能を追加して、ユーザーがプロファイルを設定できるようにする場合はどうしますか?画像?アプリケーションにいくつかの自動テストをいつか行う必要があると判断したか、バージョン管理システムでの手順の変更を追跡したいか?これらのタスクのほとんどを処理するほとんどすべての有用な言語用のライブラリとツールが多数あります。ただし、DBMSで使用できるようになるわけではないため、DBMSで使用できるものはほとんどありません。

最終的には、DBMSで直接行うことが合理的にできないようなことをしたいと思うと、行き詰まってしまいます。アプリケーション全体をDBMSで構築したので、単純な機能を追加するだけで、Webサーバーを取得して別の言語で部分の再構築を開始する以外に選択肢はありません。

アプリケーションロジックを配置する場所の名前は既にあり、理由のために「データベースストアドプロシージャ」ではなく「アプリケーションのソースコード」と呼ばれているため、これは本当に残念なことです。

6
Zach Lipton

セキュリティチェックとビジネスロジックがクライアント側のJavaScriptに含まれている場合、悪意のあるユーザーによって上書きされる可能性があります。別の方法として、 JavaScriptベースのサーバー側テクノロジー( Node.JS など)を使用して、検証、承認などを処理します。

5
Michael Brown

確認したいビジネス上の制約は、サーバー側で検証する必要があります。ユーザーアクセスを制御していても、誰かが無効なデータを送信する可能性があります。

あなたのstackoverflowクローンの例に従ってください:

  • とにかく、サイトの「クローズド」質問が編集されるのをどのようにブロックしますか?
  • コメントを削除できないようにするにはどうすればよいですか?
  • コメントの日付を偽ることをどのように防ぐことができますか?
  • 同じ投稿の50倍の賛成投票を防ぐにはどうすればよいですか。
  • もう少し掘り下げれば、おそらくもっとたくさんの例があるでしょう。

誰でもクライアント側のコードを操作し、データの整合性に完全に違反する可能性があります(自分の投稿のような特定のオブジェクトに制限されている場合でも)。

2
Jbm

Firebugでページを編集し、ある時点で次のような行を追加します。

ExecDbCommand("DROP TABLE Users")

それを実行します。

編集:

問題は実際にはCounchDBに関するものだったので、ここで実行するSQLはありませんでした。しかし、考え方は同じです。重要なアプリケーションはすべて、データに依存して、アプリケーションコードによってチェック/適用される整合性ルールを尊重すると思います。悪意のあるユーザーがクライアントコードを変更して、ビジネスルールに違反する形でデータを保存し、アプリケーションに混乱を引き起こす可能性があります。

サイトがすべての可能なデータ状態をビジネスの観点から有効であると見なしている場合は、必ずこのルートに進んでください。そうでない場合(可能性が高い)は、格納されるデータが以下によって生成されることを保証する必要があります。 your codeおよびyour rulesに従います。

1
AZ01

昔の質問ですが、私の経験は他の回答とはかなり異なるため、チャイムしたいと思いました。

私は長年、リアルタイムの共同アプリケーションを作成してきました。これらのアプリケーションの一般的なアプローチは、データをローカルに複製し、変更をできるだけ早くピアと同期させることです。データに対するすべての操作はローカルであるため、すべてのデータストレージ、データアクセス、ビジネスロジック、およびユーザーインターフェイスはローカルです。 「オフラインファースト」運動( http://offlinefirst.org/ )は、オフラインのWebアプリケーションを構築するためにこのアプローチを採用しており、いくつかの関連リソースがあるかもしれません。このような使用例では、データアクセスレイヤーをクライアントに開放するだけでなく、データストレージも必須です。分かった分かった。狂っているようですね?

このようなオフライン優先アプリの懸念は、あなたが尋ねたものと似ており、1つレベルが削除されています。私には関係があるようです。クライアントへの直接データアクセスを開いているとすると、問題は、悪意のあるユーザーの影響をどのように制限できるかということです。まあ、多くの戦略がありますが、より伝統的な開発のバックグラウンドから来ているかどうかは明らかではありません。

最初の誤解は、データベースの公開はすべてのデータの公開を意味するということです。 CouchDBを例にとります。 CouchDBのデータベースは軽量であるため、サーバー上に数十万もの個別のデータベースを作成することについて考える必要はありません。ユーザーがアクセスできるのは、リーダーまたはライター(検証機能はもちろんのこと、CouchDB以外のもの)としてアクセスする権限が付与されているデータベースだけなので、データのサブセットにしかアクセスできません。

2つ目の誤解は、ユーザーがデータをたたくのは問題だということです。ユーザーにデータベースのレプリカが与えられた場合、他のユーザーに影響を与えることなく、好きなようにデータベースを破壊できます。ただし、データを「中央」ストアに複製する前に、それらの変更を検証する必要があります。 Gitについて考えてみてください-ユーザーはマスターブランチに影響を与えることなく、ブランチ、フォーク、ローカルリポジトリで好きなことを実行できます。マスターに戻すマージは、多くの儀式を伴い、盲目的には行われません。

現在、CouchDBを使用してシステムを構築しています。このシステムでは、ユーザーがデータで共同してデータセットを構築し、QA/QCワークフローを介して「公開」する必要があります。コラボレーションはデータのレプリカで実行され(これをステージングデータベースまたは作業データベースと呼びます)、完了すると、責任者がデータに対してQA/QCを実行し、その後、データがメインリポジトリに複製されます。

従来の3層CRUDアプリケーションのバージョン管理、レプリケーション、コラボレーション(オフラインで作業を続けましょう)など、他のシステムでは実現が難しい多くの利点がこれから流れ出します。

私のアドバイス-アプリケーションが「従来の」ものである場合は、従来の方法で実行してください。上で述べた事項(もっとたくさんありますが...)が当てはまる場合は、代替アーキテクチャを検討し、横から考える準備をしてください。

1
Daniel Paull

私は、あなたのすべての仮定を考えると、クライアントからデータベースに直接移動することは実行可能だと思います。ただし、想定が有効であり、今後も有効であるかどうかを確認することは妥当です。

将来、誰もがすべてのデータを読み取るのは問題になる可能性があるわけではなく、特に将来的にはより多くのビジネスロジックが開発される可能性があるのではないかと心配しています。プロジェクトが成功した場合、これらの両方が発生する可能性が高くなります。

あなたが将来これらの問題に対処する方法を自分自身に残している限り、そして実際にそれらを処理する必要がある場合、私はあなたのデザインはうまくいくと思います。 JavaScriptコード内の問題を分離するように特に注意する必要があると思います。その一部は、後でサーバー上で書き換えられる可能性があります。

しかし、後で行う可能性があるリスクと、今日の可動部品が少ないことのメリットとの比較に、どこに価値があるのか​​は明確にわかりました。

0
psr

JavaScriptでSQLを構築してデータベースに送信する場合、セキュリティ上の理由からではなく、権限などを確認します。単にAPIを構築して構築するときクエリを自分で作成する場合は、セキュリティの観点から、限られた数のクエリのみを分析する必要があります。クエリがシステムの外部で構築されている場合、誰かが実行できるトリックが無制限に存在する可能性があります。

しかし、Key-Valueデータベースを使用しているため、そうではありません(私が理解している限り、CouchDBは一般にそのカテゴリに分類されます)。データベースインターフェース自体は一種の中間層であり、Apacheチームによってセキュリティ上の理由からテストされています。 JavaScript APIは比較的単純なため、JSFアプリケーションにあるような複雑なインターフェースよりも、潜在的な欠陥を分析する方が簡単です。

複雑なセキュリティテストを行う場合、これは安全なソリューションになります。これは、JSFなどのフレームワークを使用する場合のようにさらに簡単になる可能性があります。あいまいさによるセキュリティは解決策とは見なされません。

あなたの質問に関連して、それはとにかくデータベースへの直接アクセスではありません。直接アクセスは、JavaScriptでSQLクエリを構築することです(残念ながら、私はそのようなソリューションを見てきました)。あなたの場合、CouchDB自体が分離層を提供します。もちろん、APIでラップして強化することもできますが、特定のユーザーが何ができるかを簡単にテストでき、セキュリティの制約が機能している場合は、追加のレイヤーなしで安全で堅牢なソリューションを利用できます。

0
Danubian Sailor

まず、OUT OF THE BOXの質問に感謝します。..:)

しかし、私が提案するのは、常に3つのレイヤー間の分離を維持するようにしてください。これは、プレゼンテーション/ビジネスおよびデータベースまたはDAOです。これは、毎日多くの変更が行われるような種類の要件や設定でのベストプラクティスになるためです。

単純な世界では、プレゼンテーションレイヤーはデータベースレイヤーについて認識してはなりません。つまり、一部の日付タイプフィールドの形式はプレゼンテーションレイヤーやデータベースレイヤーとは異なる場合があるため、ユーザーは必要に応じて日付の適切な形式を自由に選択できます。

また、ビジネスロジックは、フィールドのキャストのようなプレゼンテーションレイヤーとデータベース/ Daoレイヤーの間の結合のように機能する必要があり、一部のビジネス検証などは、質問に従ってJavaScriptセクションではなくビジネスレイヤーで処理する必要があります。

この分離により、複雑なシナリオ、機能、さらには複雑な検証においても、非常に使いやすく、調和します。最大の利点は、これらのレイヤーを実装するためのさまざまなテクノロジーを使用でき、ビジネスのニーズまたはスコープに従って変更できることです。

ありがとう

0
Logicalj

2つの問題が発生します。

1。密結合: DBオプションを変更しますか?さて、クライアント側のコードもすべて変更する必要があります。私を信じて。クライアント側でこれ以上の問題は必要ありません。

2。TMIのセキュリティの問題:内容がどのように機能するかについてあまりにも多くを明らかにします。 Authは依然として障害となる可能性がありますが、サーバー側で何が起こっているかを正確に把握している場合、エクスプロイトを見つけることは非常に簡単です。

非常に薄い中間層の方が良い方法かもしれません。

0
Erik Reppen