実現したいこと
sqlのバインド変数設定後にExcuteQueryを使用し、SQLの実行とエラーハンドリングを実施したい
※ExcuteQueryはソースコードDB関連処理を参照ください
※WEBアプリのログイン機能を実装しています。
環境:Windows 11 Home
IDE:VisualStudio 2022
DB:Oracle19c
言語:VB.NET
発生している問題・分からないこと
〇ソースコード(バインド処理)内
→SQLインジェクション対策で以下のバインド処理を実施
cmd.Parameters.Add(New OracleParameter(":loginID", loginId))
cmd.Parameters.Add(New OracleParameter(":password", password))
上記方法でバインド変数を設定した場合、ExecuteScalarを使用して実行する制限があるため
用意していた実行関数が使用できず、エラーハンドリングが実施できない。
単純にSQL内にのバインド箇所に変数の値を設定すれば解決する話ではあるのですが、
SQLインジェクションの観点でバインドすべきという記事を見たので
どのようにSQLを実行し、エラーハンドリングを実施すべきか悩んでいます。
プログラミング経験が浅いためお力添えいただけないでしょうか。
該当のソースコード
DB関連処理
1Imports System.Data.Common 2Imports System.IO 3Imports Oracle.ManagedDataAccess.Client 4 5Public Class DataAccess 6 Implements IDisposable 7 8 Private conn As DbConnection = Nothing 9 Private factory As DbProviderFactory = Nothing 10 Private tran As DbTransaction = Nothing 11 Private isDisposed As Boolean = False 12 13 ' Connectionプロパティを追加 14 Public ReadOnly Property Connection As DbConnection 15 Get 16 Return conn 17 End Get 18 End Property 19 20 Public Sub New() 21 Dim dcsb As DbConnectionStringBuilder 22 23 Try 24 factory = DbProviderFactories.GetFactory("Oracle.ManagedDataAccess.Client") 25 dcsb = factory.CreateConnectionStringBuilder 26 dcsb("Data Source") = ConfigurationManager.AppSettings("dataSource") 27 dcsb("User ID") = ConfigurationManager.AppSettings("userId") 28 dcsb("Password") = ConfigurationManager.AppSettings("pass") 29 30 conn = factory.CreateConnection() 31 conn.ConnectionString = dcsb.ConnectionString 32 33 conn.Open() 34 conn = CType(conn, OracleConnection) 35 tran = conn.BeginTransaction() 36 37 Catch ex As Exception 38 LogError(ex.Message) 39 Rollback() 40 41 End Try 42 43 End Sub 44 45 Public Function ExcuteQuery(ByVal SQLContents As String) As DataSet 46 47 Dim cmd As DbCommand 48 Dim da As DbDataAdapter 49 Dim ds As New DataSet 50 51 Try 52 cmd = conn.CreateCommand 53 cmd.CommandText = SQLContents 54 55 da = factory.CreateDataAdapter() 56 da.SelectCommand = cmd 57 da.Fill(ds) 58 59 Catch ex As Exception 60 LogError(ex.Message) 61 62 End Try 63 64 Return ds 65 66 End Function 67 68 Public Function ExecuteNonQuery(ByVal SQLContents As String, Optional ByVal isCommit As Boolean = True) As Integer 69 70 Dim cmd As DbCommand 71 Dim affectedRows As Integer = 0 72 73 Try 74 cmd = conn.CreateCommand 75 cmd.CommandType = CommandType.Text 76 cmd.CommandText = SQLContents 77 78 affectedRows = cmd.ExecuteNonQuery() 79 If isCommit Then 80 Commit() 81 End If 82 83 Catch ex As Exception 84 LogError(ex.Message) 85 Rollback() 86 87 End Try 88 89 Return affectedRows 90 91 End Function 92 93 Public Sub Commit() 94 Try 95 tran.Commit() 96 tran = conn.BeginTransaction() 97 Catch ex As Exception 98 End Try 99 End Sub 100 101 Public Sub Rollback() 102 Try 103 tran.Rollback() 104 tran = conn.BeginTransaction() 105 Catch ex As Exception 106 End Try 107 End Sub 108 109 ' IDisposable の実装 110 Public Sub Dispose() Implements IDisposable.Dispose 111 Dispose(True) 112 GC.SuppressFinalize(Me) 113 End Sub 114 115 Protected Overridable Sub Dispose(disposing As Boolean) 116 If Not isDisposed Then 117 If disposing Then 118 ' マネージリソースの解放 119 If tran IsNot Nothing Then 120 tran.Dispose() 121 tran = Nothing 122 End If 123 If conn IsNot Nothing Then 124 conn.Dispose() 125 conn = Nothing 126 End If 127 End If 128 ' アンマネージリソースの解放が必要ならここで処理 129 isDisposed = True 130 End If 131 End Sub 132 133 Public Sub LogError(errorMessage As String) 134 Dim logFolder As String = "C:\Logs" 135 Dim logFile As String = Path.Combine(logFolder, "error_log.txt") 136 Dim logMessage As String = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} - {errorMessage}" 137 138 Using writer As New StreamWriter(logFile, True) 139 writer.WriteLine(logMessage) 140 End Using 141 End Sub 142 143End Class
Imports Oracle.ManagedDataAccess.Client Public Class Login Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load End Sub Protected Sub LoginButtonClick(sender As Object, e As EventArgs) Dim loginId = txtLoginID.Text Dim password = txtPassword.Text Dim sqlQuery As String = GetLoginUser() Using dataAccess As New DataAccess() Using conn As OracleConnection = dataAccess.Connection Using cmd As New OracleCommand(sqlQuery, conn) cmd.Parameters.Add(New OracleParameter(":loginID", loginId)) cmd.Parameters.Add(New OracleParameter(":password", password)) Dim result As Integer = Convert.ToInt32(cmd.ExecuteScalar()) If result > 0 Then Response.Redirect("main.aspx") Else lblMessage.Text = "ログインIDまたはパスワードが間違っています。" End If End Using End Using End Using End Sub End Class
Module Queries ' 複数行のSQL文を返す関数 Public Function GetLoginUser() As String Dim sql As String = " SELECT count(ID) FROM ユーザー WHERE ID = :loginID AND パスワード = :password " Return sql End Function End Module
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
〇試したこと
実行時のソースコードとIF文の条件をいかに変更しましたが、countが0となりエラーになります。
Dim ds As DataSet = dataAccess.ExcuteQuery(sqlQuery)
If ds.Tables.Count > 0 Then
〇調べたこと
バインド変数後のsql文の取得
→取得できないという記事しか見つけることができませんでした。
補足
特になし
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/01/11 03:13