情報処理安全確保支援士 2023年 春期 午後1 問01
Webアプリケーションプログラム開発に関する次の記述を読んで、設問に答えよ。
G社は、システム開発を行う従業員100名のSI企業である。このたび、オフィス用品を販売する従業員200名のY社から、システム開発を受託した。開発プロジェクトのリーダーには、G社の開発課のD主任が任命され、メンバーには、開発課から、Eさんと新人のFさんが任命された。G社では、セキュリティの品質を担保するために、プログラミング完了後にツールによるソースコードの静的解析を実施することにしている。
〔受託したシステムの概要〕
受託したシステムには、Y社の得意先がオフィス用品を注文する機能、Y社とY社の得意先が注文履歴を表示させる機能、Y社とY社の得意先が注文番号を基に注文情報を照会する機能(以下、注文情報照会機能という)、Y社とY社の得意先が納品書のPDFファイルをダウンロードする機能などがある。
〔ツールによるソースコードの静的解析〕
プログラミングが完了し、ツールによるソースコードの静的解析を実施したところ、Fさんが作成した納品書PDFダウンロードクラスのソースコードに問題があることが分かった。納品書PDFダウンロードクラスのソースコードを図1に、静的解析の結果を表1に示す。
この解析結果を受けて、Fさんは、Eさんの指導の下、ソースコードを修正した。表1の項番1について図1の8行目から11行目を図2に示すソースコードに修正した。項番2と項番3についてもソースコードを修正した。
再度、ツールによるソースコードの静的解析が実施され、表1の指摘は解消していることが確認された。
〔システムテスト〕
システムテストを開始したところ、注文情報照会機能において不具合が見つかった。この不具合は、ある得意先の利用者IDでログインして画面から注文番号を入力すると、別の得意先の注文情報が出力されるというものであった。なお、ログイン処理時に、ログインした利用者IDと、利用者IDにひも付く得意先コード及び得意先名はセッションオブジェクトに保存されている。
注文情報照会機能には、業務処理を実行するクラス(以下、ビジネスロジッククラスという)及びリクエスト処理を実行するクラス(以下、サーブレットクラスという)が使用されている。注文情報照会機能が参照するデータベースのE-R図を図3に、Eさんが作成したビジネスロジッククラスのソースコードを図4に、サーブレットクラスのソースコードを図5に示す。

D主任、Eさん、Fさんは、不具合の原因が特定できず、セキュアプログラミングに詳しい技術課のHさんに協力を要請した。
Hさんはアプリケーションログ及びソースコードを解析し、不具合の原因を特定した。原因は、図4で変数 e が f として宣言されていることである。
この不具合は、①並列動作する複数の処理が同一のリソースに同時にアクセスしたとき、想定外の処理結果が生じるものである。
原因を特定することができたので、Eさんは、Hさんの支援の下、次の4点を行った。
(1)図4の2行目から5行目までのソースコードを削除する。
(2)図4の6行目を、図6に示すソースコードに修正する。
(3)図5の4行目と5行目を、図7に示すソースコードに修正する。
(4)保険的な対策として、図4の10行目の抽出条件に、セッションオブジェクトに保存されたjと注文ヘッダーテーブルのjの完全一致の条件をAND条件として追加する。
ソースコードの修正後、改めてシステムテストを実施した。システムテストの結果は良好であり、システムがリリースされた。
設問1:〔ツールによるソースコードの静的解析〕について答えよ。
問題文を見る模範解答
a:13
解説
解答の論理構成
-
静的解析ツールの指摘は「ディレクトリトラバーサル」であり、 「ファイルアクセスに用いるパス名の文字列作成で、利用者が入力したデータを直接使用している。」と説明されています。
-
図1のソースコードを確認すると、入力値inOrderNoを含めてOSのパス文字列を生成している箇所は次の行です。13: File fileObj = new File(PDF_DIRECTORY + "/" + clientCode + "/" + "DeliverySlip" + inOrderNo + ".pdf");ここでinOrderNoはサーブレットから受け取った利用者入力であり、パスに直接連結されています。
-
以上より、a に該当する行番号は「13」と判断できます。
誤りやすいポイント
- 行「12: String clientCode …」を選んでしまうケース
- clientCodeも文字列ですが、ディレクトリ名生成そのものは行13で行われます。
- 「SQLインジェクション」の修正箇所(8〜11行目)と混同するケース
- 同じ入力値inOrderNoを扱っているため要注意です。
- 「ファイル存在確認 → 入力チェック済み」と早合点するケース
- 存在確認の前にファイルパスが生成されている点を見落としがちです。
FAQ
Q: 「clientCode」も入力値ですが、なぜ12行目ではなく13行目なのですか?
A: 12行目はデータベースから値を取り出す処理であり、まだパス操作を行っていません。実際にパスを合成しているのは13行目です。
A: 12行目はデータベースから値を取り出す処理であり、まだパス操作を行っていません。実際にパスを合成しているのは13行目です。
Q: ディレクトリトラバーサルは絶対パスでなければ発生しないのでは?
A: 相対パスでも ../../ などを含めれば親ディレクトリへ遷移できます。文字列連結でガードしていない以上、脆弱性は存在します。
A: 相対パスでも ../../ などを含めれば親ディレクトリへ遷移できます。文字列連結でガードしていない以上、脆弱性は存在します。
Q: 入力チェックを後段で行えば問題ありませんか?
A: パス生成前にホワイトリスト方式で検証するのが基本です。後段で検出できなかった場合、攻撃が成立してしまいます。
A: パス生成前にホワイトリスト方式で検証するのが基本です。後段で検出できなかった場合、攻撃が成立してしまいます。
関連キーワード: ディレクトリトラバーサル、静的解析、パス操作、入力値検証、セキュアコーディング
設問1:〔ツールによるソースコードの静的解析〕について答えよ。
問題文を見る模範解答
b:in
解説
解答の論理構成
- 表1の指摘内容には「変数stmt、変数resultObj、変数bが指すリソースが解放されない。」とあります。
- 図1のリソース生成箇所を確認すると、次の3種類のリソースが生成されています。
• 10行目:Statement stmt = conn.createStatement();
• 11行目:ResultSet resultObj = stmt.executeQuery(sql);
• 14行目:BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileObj)); - 表1で既に列挙済みのstmtとresultObjに続く“3番目のリソース”は、図1の14行目で生成されたBufferedInputStream型の変数です。ここで使われている変数名は「in」です。
- よって、b に入る適切な変数名は「in」になります。
誤りやすいポイント
- bufと回答してしまう
- byte[] buf = new byte[in.available()] はメモリ領域の確保であり、ファイルやストリームのような「外部リソース」ではないため解放対象ではありません。
- fileObjと回答してしまう
- Fileオブジェクト自体はディスクリプタを保持せず、明示的なcloseは不要です。
- ソース全体を見ずに行番号だけに着目する
- 表1の指摘は行番号ではなく「リソース解放漏れ」に関する網羅性を問うため、登場する全てのリソース型変数を確認する必要があります。
FAQ
Q: どうしてBufferedInputStreamをcloseしなければならないのですか?
A: 入出力ストリームはOSのファイルディスクリプタを使用します。closeしない場合、ディスクリプタが枯渇し、他の処理がファイルを開けなくなる恐れがあります。
A: 入出力ストリームはOSのファイルディスクリプタを使用します。closeしない場合、ディスクリプタが枯渇し、他の処理がファイルを開けなくなる恐れがあります。
Q: try-with-resourcesを使えば解放漏れは防げますか?
A: はい。Java7以降であればtry (BufferedInputStream in = …) のように書くことで、例外が発生しても自動的にcloseされます。
A: はい。Java7以降であればtry (BufferedInputStream in = …) のように書くことで、例外が発生しても自動的にcloseされます。
Q: Fileクラスはなぜ解放が不要なのですか?
A: Fileオブジェクトはファイルシステム上のパスを表すだけであり、実際のファイルハンドルを保持しないため、クローズ処理は必要ありません。
A: Fileオブジェクトはファイルシステム上のパスを表すだけであり、実際のファイルハンドルを保持しないため、クローズ処理は必要ありません。
関連キーワード: ストリーム、リソース解放、try-with-resources, ファイルディスクリプタ
設問1:〔ツールによるソースコードの静的解析〕について答えよ。
問題文を見る模範解答
c:WHERE head.order_no = ?
d:PreparedStatement stmt = conn.prepareStatement(sql)
解説
解答の論理構成
- 静的解析ツールが指摘した項番1は「SQLインジェクション」です。図1の
sql = sql + " WHERE head.order_no = '" + inOrderNo + "' ";
という記述は、利用者入力inOrderNoを文字列連結しており、攻撃者が任意のSQLを注入できる危険があります。 - 図2ではこの脆弱性を除去するため、SQL 文にプレースホルダを用いて PreparedStatement でバインド方式に変更しています。したがって c には「プレースホルダ付き WHERE 句」をそのまま文字列として設定する必要があります。
・従来の文字列連結部分をそのまま残すと意味がない
・setStringで1番目のパラメータへinOrderNoを束縛するため、? が1個だけ必要
よって c は
WHERE head.order_no = ?
が適切です。 - Statementを生成していた10行目もプレースホルダ処理に合わせてPreparedStatementに置き換えます。図2の d には
PreparedStatement stmt = conn.prepareStatement(sql)
が入ることが示されています(模範解答より)。 - 最終的に、
sql = sql + " WHERE head.order_no = ? ";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, inOrderNo);
という形になり、ユーザ入力がSQL文に直接挿入されないため、指摘事項「SQLインジェクション」が解消されます。
誤りやすいポイント
- プレースホルダ ? の前後に引用符 ' を残す
(例:WHERE head.order_no = '?')とバインド時に型不一致や検索失敗を招きます。 - PreparedStatement生成後にexecuteQuery(sql) を呼び出す
(正しくはexecuteQuery())。ツールでは検出されても実行時にエラーになります。 - setStringの添字を0から始めるとjava.sql.SQLExceptionが発生します。JavaのJDBCは1始まりです。
FAQ
Q: 単に WHERE head.order_no = ' で始めて最後に ' を付け、その間を ? と置き換えてはだめですか?
A: その方法だとプレースホルダがシングルクォートで囲まれた文字列リテラル扱いとなり、JDBCが値をバインドできません。? だけを記述し、JDBCドライバに型とエスケープ処理を任せるのが正しい実装です。
A: その方法だとプレースホルダがシングルクォートで囲まれた文字列リテラル扱いとなり、JDBCが値をバインドできません。? だけを記述し、JDBCドライバに型とエスケープ処理を任せるのが正しい実装です。
Q: PreparedStatementにしてもSQLを連結する別の場所が残っていると危険ですか?
A: はい。PreparedStatementを使用しても、プレースホルダ以外の部分にユーザ入力を連結してしまうと、同様のSQLインジェクションが発生します。全てのユーザ入力は必ずバインド変数に設定することが重要です。
A: はい。PreparedStatementを使用しても、プレースホルダ以外の部分にユーザ入力を連結してしまうと、同様のSQLインジェクションが発生します。全てのユーザ入力は必ずバインド変数に設定することが重要です。
Q: 単純な検索なので入力チェックだけで良いのでは?
A: 文字列検証は有効ですが完全ではありません。入力チェック+プリペアドステートメントの多層防御でリスクを最小化することが推奨されます。
A: 文字列検証は有効ですが完全ではありません。入力チェック+プリペアドステートメントの多層防御でリスクを最小化することが推奨されます。
関連キーワード: SQLインジェクション、PreparedStatement, プレースホルダ、バインド変数、静的解析
設問2:〔システムテスト〕について答えよ。
問題文を見る(1)本文中のeに入れる適切な変数名を、図4中から選び、答えよ。
模範解答
e:orderNo
解説
解答の論理構成
- 【問題文】には「原因は、図4で変数 e が f として宣言されていることである。」とある。
- 図4の2行目には「private static String orderNo; //注文番号」と記載されており、ここで使われている変数名が e に該当する。
- したがって e に入る変数名は「orderNo」となる。
- さらに図4の8行目以降で「psObj.setString(1, orderNo);」と利用されていることから、注文番号を保持する目的の変数であると確認できる。
- 以上より、e の正答は【 orderNo 】となる。
誤りやすいポイント
- 静的解析で指摘された納品書PDFダウンロードクラス(図1・図2)と、今回問われているビジネスロジッククラス(図4)を混同してしまう。
- 「static」の有無だけに注目し、変数名を見落とすと「orderNo」以外のキーワードを記入してしまう。
- 図5のサーブレット側にも「orderNo」が局所変数で登場するため、両者を区別しないと混乱しやすい。
FAQ
Q: なぜ「static」が付いていると不具合になるのですか?
A: 複数スレッド(複数ユーザ)が同時にアクセスする場合、クラス変数は共有されるため、先にセットした注文番号が後続処理で上書きされ、別ユーザのデータが返却される競合が起きるからです。
A: 複数スレッド(複数ユーザ)が同時にアクセスする場合、クラス変数は共有されるため、先にセットした注文番号が後続処理で上書きされ、別ユーザのデータが返却される競合が起きるからです。
Q: サーブレット側でnewしたオブジェクトに移行したのはどのような意図ですか?
A: インスタンス変数にすれば各リクエストごとに独立した値を保持できるため、スレッドセーフになり誤動作を防止できます。
A: インスタンス変数にすれば各リクエストごとに独立した値を保持できるため、スレッドセーフになり誤動作を防止できます。
Q: セッションオブジェクトで得意先コードを AND 条件に追加した理由は?
A: 万一ロジック層に再び競合が発生しても、データベース検索結果が他得意先に漏れないように“保険的”に絞り込むためです。
A: 万一ロジック層に再び競合が発生しても、データベース検索結果が他得意先に漏れないように“保険的”に絞り込むためです。
関連キーワード: 共有変数、スレッドセーフ、同期不良、クラス変数、インスタンス化
設問2:〔システムテスト〕について答えよ。
問題文を見る(2)本文中のfに入れる適切な字句を、英字10字以内で答えよ。
模範解答
f:static
解説
解答の論理構成
- 【問題文】には「原因は、図4で変数 e が f として宣言されていることである。」とあり、図4の2行目には
2: private static String orderNo;
と示されています。ここから f に入る語がstaticであることが読み取れます。 - static修飾子で宣言したフィールドはクラスに一つしか存在せず、全スレッド・全インスタンスで共有されます。
- 【問題文】では不具合の性質を「①並列動作する複数の処理が同一のリソースに同時にアクセスしたとき、想定外の処理結果が生じる」と説明しています。orderNoが共有されてしまうため、あるリクエストがOrderInfoBL.setOrderNoで値を設定した直後に、別のリクエストが上書きし、最初のリクエストが誤った注文番号で検索を実行する ―― まさに並行アクセスによるレースコンディションです。
- よって f にはstaticが入ります。
誤りやすいポイント
- privateやStringといったキーワードを原因と勘違いし、アクセス修飾子や型に意識が向き過ぎる。
- staticメソッドとstaticフィールドを混同し、「メソッドがstaticだから問題」と誤解する。実際の不具合はフィールド共有によるものです。
- 「Servletはシングルスレッドで動く」と思い込み、マルチスレッド環境でのクラス変数共有問題を軽視する。
FAQ
Q: staticを外せば必ず安全になるのでしょうか?
A: インスタンスフィールドに変更することで少なくともスレッド間で値を共有しなくなり、今回の誤動作は防げます。ただし、他に共有リソースがある場合は別途排他制御が必要です。
A: インスタンスフィールドに変更することで少なくともスレッド間で値を共有しなくなり、今回の誤動作は防げます。ただし、他に共有リソースがある場合は別途排他制御が必要です。
Q: synchronizedでメソッドを囲めばstaticのままでも良いのでは?
A: 排他制御で競合は防げますが、全リクエストが同じロックを待つことになり性能劣化の原因になります。本設計ではリクエストごとに独立した値を持たせる方が適切です。
A: 排他制御で競合は防げますが、全リクエストが同じロックを待つことになり性能劣化の原因になります。本設計ではリクエストごとに独立した値を持たせる方が適切です。
Q: Servletで状態を持つときはどうすれば良い?
A: セッションスコープやリクエストスコープなど、スレッドごとに分離された領域に保存してください。共有が必要な場合だけスレッドセーフな構造(例:ConcurrentHashMap)を使います。
A: セッションスコープやリクエストスコープなど、スレッドごとに分離された領域に保存してください。共有が必要な場合だけスレッドセーフな構造(例:ConcurrentHashMap)を使います。
関連キーワード: 共有変数、レースコンディション、スレッドセーフ、セッション管理、サーブレット
設問2:〔システムテスト〕について答えよ。
問題文を見る(3)本文中の下線①の不具合は何と呼ばれるか。15字以内で答えよ。
模範解答
レースコンディション
解説
解答の論理構成
- 【問題文】では「①並列動作する複数の処理が同一のリソースに同時にアクセスしたとき、想定外の処理結果が生じる」と明記されています。
- この現象は、処理(スレッドやプロセス)間でリソース共有の同期が取れていないために発生します。
- コンピュータシステムの典型的な障害分類では、上記のような“同時アクセスによる競合”を「レースコンディション」と呼びます。
- よって、設問の下線①の不具合名は「レースコンディション」と判断できます。
誤りやすいポイント
- 「デッドロック」と混同する
同期が取れていない点は同じですが、デッドロックは“お互いがロックを待ち続けて停止する”状態であり、想定外のデータ混在や上書きは起きません。 - 「クリティカルセクション」がキーワードだと思い違いする
クリティカルセクションは対策概念であり、不具合名ではありません。 - “競合状態”を日本語そのままで書いてしまう
出題は正式な用語を求めているため、「レースコンディション」と記述する必要があります。
FAQ
Q: レースコンディションはマルチスレッド環境だけの問題ですか?
A: いいえ。マルチプロセスや分散処理など複数主体が同一リソースにアクセスするすべての場面で起こり得ます。
A: いいえ。マルチプロセスや分散処理など複数主体が同一リソースにアクセスするすべての場面で起こり得ます。
Q: 防止策はロックを掛けるだけで十分ですか?
A: 排他制御(ロック、同期化)は基本対策ですが、タイムアウト設定やトランザクション分離レベルの見直しも重要です。
A: 排他制御(ロック、同期化)は基本対策ですが、タイムアウト設定やトランザクション分離レベルの見直しも重要です。
Q: ログ調査でレースコンディションをどう見抜くのですか?
A: 同一リソースに対するアクセス時刻が極端に近接し、処理結果が交互に上書きされている痕跡などがヒントになります。
A: 同一リソースに対するアクセス時刻が極端に近接し、処理結果が交互に上書きされている痕跡などがヒントになります。
関連キーワード: race condition, concurrency, synchronization, shared resource
設問2:〔システムテスト〕について答えよ。
問題文を見る模範解答
g:String orderNo
h:new
i:getOrderInfoBean(orderNo)
解説
解答の導き方
-
修正内容の確認
- 「(1)図4の2行目から5行目までのソースコードを削除する」とあるため、以前のようにクラス内の静的変数とセッタで注文番号を共有する方式はやめています。
- 図6に「public OrderInfoBean getOrderInfoBean(g) {」とあり、getOrderInfoBeanが引数を受け取るように変更されたことが示されています。
- 図7に「OrderInfoBL orderInfoBLObj = h OrderInfoBL();」および「OrderInfoBean orderInfoBeanObj = orderInfoBLObj.i;」とあるので、サーブレット側でOrderInfoBLのインスタンスを作成し、そのインスタンスのメソッドを呼んでいることが分かります。
- 図5に「3: String orderNo; //注文番号」とあり、サーブレット側で注文番号はString型の変数orderNoとして保持していることが分かります。
-
g(メソッド引数)の決定理由
- getOrderInfoBeanは注文番号を外部から受け取って処理する設計に変更されたため、引数は注文番号の型に合わせる必要があります。サーブレットの変数は「String orderNo」であるので、引数の型はStringです。
- 引数名については呼び出し側の変数名と一致している必要はありません(Javaでは型と順序が一致すれば呼び出せます)が、図7で実際に渡しているのがorderNoであることから、問題の文脈では「String orderNo」が最も自然で適切です。
- 以上より、図6の g には 「String orderNo」が入ります。
-
h(インスタンス生成演算子)の決定理由
- 図7の左辺はローカル変数にインスタンスを代入する形になっており、右辺にはOrderInfoBLの生成式が入るべきです。Javaでオブジェクトを生成する演算子はnewです。
- したがって、図7の h には 「new」が入ります。
-
i(メソッド呼び出し)の決定理由
- 図6でgetOrderInfoBeanが引数を取るようになったため、図7での呼び出しも引数付きで行う必要があります。サーブレット側の注文番号変数は「orderNo」なので、呼び出しはgetOrderInfoBean(orderNo) です。
- 以上より、図7の i には 「getOrderInfoBean(orderNo)」が入ります。
以上の流れから、図6・図7の穴埋めはそれぞれ「String orderNo」「new」「getOrderInfoBean(orderNo)」となります。
誤りやすいポイント
- DeliverySlipBLや別箇所にある引数名の「inOrderNo」と混同して「String inOrderNo」を選んでしまう。図5ではサーブレット側の変数が「String orderNo」である点を優先すること。
- メソッドの引数名は呼び出し側と同じである必要はないと混乱する(型が一致すれば呼び出せる)が、設問文の図7の記述と整合する名前を答えること。
- インスタンスメソッドを呼ぶのにインスタンス生成を忘れて静的呼び出しの形にしてしまう(newを入れない/入れ方を誤る)。
- getOrderInfoBeanに引数が必要になっているのに空の呼び出しgetOrderInfoBean() を書くミス。
- 根本原因を見落とし、static変数を残したままにして並行実行の不具合を解消していない理解で回答するミス。
FAQ
Q: 図6の引数に「String inOrderNo」と書いてもコンパイルは通りますか?
A: 型と順序が合っていればコンパイルは通ります(引数名はローカル識別子なので呼び出し側と一致する必要はない)が、問題文の図7ではサーブレットの変数名がorderNoであり、設問の意図として「String orderNo」を答えるのが妥当です。
A: 型と順序が合っていればコンパイルは通ります(引数名はローカル識別子なので呼び出し側と一致する必要はない)が、問題文の図7ではサーブレットの変数名がorderNoであり、設問の意図として「String orderNo」を答えるのが妥当です。
Q: 図7の h は本当に「new」でしかありえませんか?
A: 図7の形はインスタンス生成式を右辺に置くパターンなので、Javaでの生成演算子「new」を入れてnew OrderInfoBL() とするのが正解です。他の語を入れると文法的に不正になります。
A: 図7の形はインスタンス生成式を右辺に置くパターンなので、Javaでの生成演算子「new」を入れてnew OrderInfoBL() とするのが正解です。他の語を入れると文法的に不正になります。
Q: なぜsetOrderNoを使う以前の実装が問題だったのですか?
A: 以前はクラス内の静的変数で注文番号を共有しており、並列実行時に別スレッドの値で上書きされる可能性がありました。インスタンス化して引数で渡す設計にすると、その共有がなくなり競合を防げます。
A: 以前はクラス内の静的変数で注文番号を共有しており、並列実行時に別スレッドの値で上書きされる可能性がありました。インスタンス化して引数で渡す設計にすると、その共有がなくなり競合を防げます。
関連キーワード: インスタンス化、静的変数、スレッドセーフ、メソッド引数、リソース競合、PreparedStatement
設問2:〔システムテスト〕について答えよ。
問題文を見る(5)本文中のjに入れる適切な属性名を、図3中から選び、答えよ。
模範解答
j:得意先コード
解説
解答の論理構成
-
セッションに保持されている情報を確認
- 【問題文】「ログイン処理時に、ログインした利用者IDと、利用者IDにひも付く得意先コード及び得意先名はセッションオブジェクトに保存されている。」
⇒ セッションには「得意先コード」が格納済みです。
- 【問題文】「ログイン処理時に、ログインした利用者IDと、利用者IDにひも付く得意先コード及び得意先名はセッションオブジェクトに保存されている。」
-
追加すべき抽出条件の指示内容を確認
- 【問題文】「図4の10行目の抽出条件に、セッションオブジェクトに保存されたjと注文ヘッダーテーブルのjの完全一致の条件をAND条件として追加する。」
⇒ セッションにある属性と注文ヘッダーテーブル上の同一属性を照合する必要があります。
- 【問題文】「図4の10行目の抽出条件に、セッションオブジェクトに保存されたjと注文ヘッダーテーブルのjの完全一致の条件をAND条件として追加する。」
-
注文ヘッダーテーブルに存在する対応属性を確認
- 【図3】注文ヘッダーテーブルの属性一覧に「得意先コード」が存在。
- 利用者マスターにも「得意先コード」が存在し、セッション保持情報とも一致。
-
上記1〜3から、セッションと注文ヘッダーテーブルの両方に共通に存在し完全一致を取るべき属性は「得意先コード」であると結論付けられます。
誤りやすいポイント
- 「利用者ID」と誤認する
セッションには利用者IDも保存されますが、注文ヘッダーテーブルには利用者IDが存在しないため抽出条件に使えません。 - 「注文番号」を選択する
既に WHERE 句で完全一致条件が設定済み(図4 13行目)なので追加条件には該当しません。 - 「得意先名」を選ぶ
文字列表記ゆれや重複のリスクがあり、リレーションも外部キーではないため誤りです。
FAQ
Q: 「得意先コード」をAND条件に加えるとどのような効果がありますか?
A: ログイン中の得意先に属する注文だけを抽出でき、別得意先の注文情報が誤って取得・表示されることを防ぎます。
A: ログイン中の得意先に属する注文だけを抽出でき、別得意先の注文情報が誤って取得・表示されることを防ぎます。
Q: 既に注文番号で検索しているのに追加条件が必要な理由は?
A: 静的変数の共有などプログラムミスが残る可能性に備えた保険的対策として、得意先コードでも絞り込むことで多層防御となります。
A: 静的変数の共有などプログラムミスが残る可能性に備えた保険的対策として、得意先コードでも絞り込むことで多層防御となります。
Q: 得意先コードをパラメータ化せずにSQL文字列へ連結してもよいですか?
A: SQLインジェクション対策としてパラメータ化(PreparedStatementなど)を行い、得意先コードもバインド変数で渡すべきです。
A: SQLインジェクション対策としてパラメータ化(PreparedStatementなど)を行い、得意先コードもバインド変数で渡すべきです。
関連キーワード: セッション管理、AND条件、外部キー、多層防御、SQLインジェクション











