web-dev-qa-db-ja.com

主キーを公開しないのはなぜですか

私の教育では、実際の主キー(DBキーだけでなく、すべての主アクセサー)をユーザーに公開するのは欠陥のあるアイデアだと言われました。

私はいつもそれをセキュリティの問題だと思っていました(攻撃者が自分のものではないものを読み取ろうとする可能性があるためです)。

ユーザーにアクセスが許可されているかどうかを確認する必要があるので、その背後に別の理由がありますか?

また、ユーザーはとにかくデータにアクセスする必要があるため、その間のどこかにある外界の公開鍵が必要になります。これで、公開鍵には主鍵と同じ問題がありますね。


とにかくなぜそうするのかという例のリクエストがあったので、ここに1つあります。質問は、この例に当てはまる場合だけでなく、原則自体に関するものであることに注意してください。他の状況に対処する回答は明示的に歓迎されます。

アクティビティを処理し、複数のUIとシステム間通信用の少なくとも1つの自動APIを備えたアプリケーション(Web、モバイル)(たとえば、経理部門は、何が行われたかに基づいて顧客に請求する金額を知りたいと思っています)。アプリケーションには複数の顧客がいるため、データの分離(論理的には、データは同じDBに格納されます)はシステムに必須です。各リクエストは、何があっても有効性がチェックされます。

アクティビティは非常に細かいので、いくつかのコンテナオブジェクトにまとめられています。これを「タスク」と呼びます。

3つのユースケース:

  1. ユーザーAは、ユーザーBをタスクに送信したいので、アクティビティ(アクティビティ)を実行するためのリンク(HTTP)を送信します。
  2. ユーザーBは建物の外に出て、モバイルデバイスでタスクを開く必要があります。
  3. 会計は顧客にタスクの料金を請求したいが、REST-アプリケーションのAPIを参照するコードによってタスク/アクティビティを自動的にロードするサードパーティの会計システムを使用します

それぞれのユースケースでは、エージェントがタスクとアクティビティのアドレス指定可能な識別子を持つ必要があります(または、簡単になります)。

54
Angelo Fuchs

これは、他の答えの組み合わせの答えです(私が学んだこと)。これに賛成票を投じるつもりがある場合は、実際の作業を行っただけでなく、少なくとも他のいずれかを賛成票に入れるべきです。もっと興味があれば、代わりに他の答えを読んでください。

データベースの主キーを公開するのではなく、代理キーを使用する必要があります

  1. ユーザーがエントリを(少なくとも少し)覚えたり、識別したりできるようにしたい場合。 ( Graystone28s Answer
  2. 事前に計画を立て、システム(データベースなど)を変更する可能性があることを考慮すると、PKが変更される可能性があります。 ( Telastyns Answer
  3. 会社が所有権を変更した場合でもデータが別のシステムに完全に移行されても変更されないデータにユーザーが一貫した方法でアクセスできるようにしたい場合。 ( Michael Durrants Answer
  4. PKが(シーケンスのように)予測可能である場合、システムはリソース獲得の問題を抱えている可能性があります。 ( CodeCasters Answer )これは、システムに収穫に値する情報があり、収穫に関心のある人または少なくとも誰かがアクセスできる場合にのみ適用されます。

注:作成したキーは、(やや)人間が理解できるもの( Sqlvogels Answer )である必要があります。

システムに1.〜4.が必要ない場合は、データベースPKを公開識別子として使用しない理由はありません(いくつかの回答)。また、セキュリティはここでは問題ではありません(回答のいくつか)。

10
Angelo Fuchs

また、ユーザーはとにかくデータにアクセスする必要があるため、その間のどこかにある外界の公開鍵が必要になります。

丁度。ステートレスHTTPを取り上げます。そうでなければ、リクエストする必要があるリソースがわかりません。URLに質問のID 218306が公開されます。おそらく、公開された識別子が予測可能であるかどうかを実際に疑問に思っているかもしれません。

それに対する否定的な答えを聞いた唯一の場所は、その根拠を使用しました:"しかし、彼らはURLのIDを変更することができます!"。そのため、適切な認証を実装する代わりにGUIDを使用しました。

識別子を予測可能にしたくない1つの状況を想像できます。それはリソースの収穫です。特定のリソースを公開してホストしているサイトで、他の人が興味を持っている可能性があり、/images/n.jpgまたは/videos/n.mp4のようにホストしている場合、nは増加する数であり、そしてあなたのウェブサイトからあなたのすべてのリソースを収穫することができます。

したがって、あなたの質問に直接答えるには、いいえ、プログラムにのみ意味がある識別子を直接「公開」することは悪くありません。通常、プログラムが正常に動作するために必要です。

40
CodeCaster

それを見る人はそれを本来の「口座番号」として使用し始めるので、それを公開すべきではありません。たとえば、私の銀行口座の場合、口座番号が何であるかを知っています。私はそれを記憶しました、カスタマーサービスと電話で使用します。他の銀行が送金を行うためのフォームに入力するとき、法的文書、自動支払いサービスなどのために使用します。変更します。一方、(私のアカウントの)主キーはわかりません。
それを保存するシステムは、銀行の合併、システムのアップグレードと交換などを通じて、あるシステムから別のシステムに長年にわたって変化します。
主キーはこれらの変換の一部によって変更される可能性があるため、公開されていない、書き留められていない、または正規のユーザーが本当の良いことを覚えていない場合
ビジネス上の意味がないキーは、しばしばサロゲートキーと呼ばれ、多くの場合(常にではありませんが)主キーとして使用されます。

ところで、これは、主キーを誤用して公開し、それらをそのようなシステムの一部にするインターフェースやプログラムを構築したときに、内部で発生するだけでなく、内部でデータベースレコードを一意に識別するというものです。私は実際に、病院のデータウェアハウスシステムをサポートする6年間の経験を通して、上記のことを学びました。

29
Michael Durrant

主キーは実装の詳細だからです。

データベースを移行する場合、古いレコードの挿入、削除の順序によって主キーが変更される可能性があります...いくつかの異なる理由。データベースを移行する場合platforms実際の主キーがまったくない可能性があります。 PKをデータアクセス層の上に公開することは、リークのある抽象化であり、結合に関するすべての懸念事項が伴います。

28
Telastyn

私が見つけた1つの理由は、エンドユーザーが自分の識別子が何かを意味することを要求するのを見てきました(接頭辞、またはそれが受け入れられた年のインジケーターなど)。 PKを変更するのは難しいですが、代理がはるかに簡単です。

主キーは、パフォーマンス上の理由からデータベースのインデックスを作成したいものである可能性が高く、技術的な理由により、それを例えば数値からガイドに変更する可能性があります...新しいテクノロジーや知識の理由がわからないだけですあなたを案内するかもしれません。あなたのpkはあなたのデータの技術的なアイテムであり、公開鍵はエンドユーザーの消費のためのものです。

8
Wayne M

ほとんどのアプリケーションでは、ユーザーにキーを公開することが非常に重要です。情報システムを効果的に使用するには、そのシステムのユーザーは通常、システム内の情報を識別し、その情報をデータベース外の世界の何かに関連付ける方法が必要です。リレーショナルデータベースの用語では、これらの識別子はキーです。

よく使用される設計パターンの1つは、抽象化の手段として、データベーステーブルに純粋に「技術的な」追加のキーを作成することです。たとえば、いくつかの代替キーが変更される可能性がある安定した(比較的変化しない)キーを提供する場合。このようなテクニカルキーは、ユーザーの要件から意図された抽象化を損なうため、通常、エンドユーザーには公開されません。セキュリティとは何の関係もありません。

あなたの質問に内在する問題/誤解は、用語primary keyの不適切な使用が原因です。主キーは、いくつかの「候補」キー(データベーステーブル内のいくつかの可能な識別子)のうちの1つにすぎません。主キーは必ずしも他のキーと根本的に異なるプロパティを必要としないため、主キーにのみ適用され、他のキーには適用されないアサーションと設計原則は常に疑わしく、多くの場合間違っています。

通常、ユーザーにキーを公開する必要があるとすると、そのキーはどうあるべきですか?キーを親しみやすく、シンプルで安定したものにしてください。親しみやすさとシンプルさにより、キーが読みやすく、覚えやすくなり、データ入力エラーを回避できます。安定性とは、キーの変更がまれであることを意味し、誤認の可能性を回避するのにも役立ちます。

2
nvogel

エンティティが外部の世界に公開される一意の識別子を持っていることは完全に正常です。一部のオブジェクトについては、実際に意味を持つ識別子(請求書番号など)を見つけることができる場合がありますが、他のオブジェクトについてはそのような識別子が存在しないため、生成する必要があります。

一貫性と読みやすさのために、システム内のすべてのエンティティーが、それらのIDにまったく同じタイプと名前を使用することをお勧めします。通常、この識別子はいくつかの抽象基本クラスで公開されます(<type> getId())。

同じ理由で、システム内の各サービス(請求サービスなど)は、エンティティの識別子でアクセスするための同じメソッドを提供する必要があります。通常、このメソッド(findById(<type> id))は、汎用サービスインターフェイスまたは基本クラスから継承されます。

この識別子はエンティティの主キーである必要はありませんが、1つでもかまいません。確認しなければならない唯一のことは、キー生成戦略が合理的に一意の識別子を生成することです(普遍的に一意である必要はありませんが、少なくともシステム内で)。

システムが後で別のデータベースに移行された場合(私の経験では大きい)、元の戦略と互換性がある限り、識別子の作成に別の戦略(主キーに基づいていない)を使用しても問題はありません。

1
Muton

これは、CodeCasterによるGreystone28の回答に対するコメントからです。それはあなたが言っていることの例です:

私は顧客に対して意味があり、変更可能なInvoiceNumberを公開しますが、私のコードが請求書を一意に識別するために使用するInvoiceIDも公開します。ユーザーキーをストレージキーにする必要はありません(多くの場合、そうしたくない)。この質問は後者についてです。

アプリでInvoiceIDを表示する目的は何ですか?

公開するとは、ユーザーがそれを見ることができるということを想定しています。ユーザーがアプリを使用するために必要な場合にのみ公開します。技術サポートやいくつかの管理スタッフが使用できます。私はこれを行ういくつかのアプリを使用してきました。問題の特定のレコードを知っている場合、サポートを提供しやすくなります。

1
JeffO

主キーは、開発者としてアクセスしようとしているタプル(レコード、行)のハンドルと同じです。また、参照整合性(外部キー制約)でも使用され、1つ以上のユースケースもある可能性があります。

基本的に、それをユーザーやハッカーに公開することは悪いことではありません。たとえば、主キーを使用する攻撃を知らないからです。

しかし、セキュリティに関しては、私たちには多くの原則(私たちは受け入れ、承認しません)があり、それらを守る必要があります。

  1. リース特権の原則
  2. あいまいさによるセキュリティ

そして他のいくつかの原則。彼らが本質的に言っているのは、

データを公開する必要がない場合は、なぜそんなことをするのですか?

0
Saeed Neamati