2016-11-03 1 views
0

아래 코드는 데이터베이스에서 데이터를 검색하는 안전한 방법을 구현합니까? 제발 도와주세요, 나는 SQL 주입에 대해 이해하지 못합니다. 누군가이 코드를 쉽게 주입 할 수 있다고 말했습니다. 그렇다면 누군가가 설명 할 수 있습니까? 고맙습니다.데이터베이스에서 일부 값을 반환하는 안전한 방법 (SQL SERVER 및 ASP.NET)

public int CheckID(string column, string table, string wheres) 
    { 
     int i = 0; 
     sqlcon = ConnectToMain(); 
     string sqlquery = "SELECT "+column+" FROM "+table+" "+wheres+""; 
     using (sqlcon) 
     { 
      sqlcon.Open(); 
      SqlCommand sqlcom = new SqlCommand(sqlquery, sqlcon); 
      using (sqlcom) 
      { 
       SqlDataReader dr = sqlcom.ExecuteReader(); 
       dr.Read(); 
       if (dr.HasRows) 
       { 
        i = dr.GetInt32(0); 
       } 
       else 
       { 
        i = 0; 
       } 
      } 
      sqlcon.Close(); 
     } 
     return i; 
    } 
+1

시작 : http://stackoverflow.com/questions/332365/how-does-the-sql-injection-from-the-bobby-tables-xkcd-comic-work – Steve

+0

이 코드 버그가 많아서 심지어 실행 (당신이 연결을 열어 깜빡). 또한 연결 누설을 암시합니다.'sqlcon'은 정의되어 있지 않습니다. 이는 지워지지 않는 필드라는 의미입니다. 아마 다른 방법으로도 적절히 닫히지 않을 것입니다. –

+0

@ 스티브 링크에 감사드립니다. 매우 도움이됩니다. –

답변

1

이 코드는 너무 많은 문제가 있습니다.

  • 테이블, 열 및 조건은 문자열로 전달되고 연결됩니다. 즉 코드가 SQL 주입을 받기 쉽습니다.
  • 테이블, 열 조건과 같은 데이터베이스 세부 정보가 함수의 호출자로 유출됩니다. 이 메서드를 사용하여 Visitor 테이블이 아닌 다른 쿼리를 수행 할 예정입니까?
  • 단일 값만 원할 경우 판독기가 사용됩니다.
  • 연결이 using 블록 외부에서 만들어져 필드에 저장됩니다. 이것은 분명히 메모리 누수 일 뿐이며 아마도 연결 유출 일 것입니다. 연결을 로컬로 만 만들면됩니다.

간단한 명령 호출 수정이 모든 문제 :

public int CheckIDVisitor(visitorName) 
{ 
    string query = "SELECT ID FROM Visitors where [email protected]"; 
    using (var sqlConn=new SqlConnection(Properties.Default.MyDbConnectionString)) 
    using(var cmd=new SqlCommand(query,sqlConn)) 
    { 
     var cmdParam=cmd.Parameters.Add("@name",SqlDbType.NVarChar,20); 
     cmdParam.Value=visitorName; 
     sqlConn.Open(); 

     var result=(int?)cmd.ExecuteScalar(); 
     return result??0; 
    } 
} 

또한 사전에 명령을 생성하고 필드에 저장할 수 있습니다.

public int CheckIDVisitor(visitorName) 
{ 
    using (var sqlConn=new SqlConnection(Properties.Default.MyDbConnectionString)) 
    { 
     string sql = "SELECT ID FROM Visitors WHERE [email protected]" 
     var result = conn.Query<int?>(sql, new { name = visitorName); 
     return result??0; 
    } 
} 
:

public void InitVisitorCommand() 
{ 
    string query = "SELECT ID FROM Visitors where [email protected]"; 
    var cmd=new SqlCommand(query,sqlConn); 
    var cmdParam=cmd.Parameters.Add("@name",SqlDbType.NVarChar,20); 
    _myVisitorCommand=cmd; 
} 

... 

public int CheckIDVisitor(visitorName) 
{ 
    using (var sqlConn=new SqlConnection(Properties.Default.MyDbConnectionString)) 
    { 
     _myVisitorCommand.Parameters.["@name"]Value=visitorName; 
     _myVisitorCommand.Connection=sqlConn; 
     sqlConn.Open(); 

     var result=(int?)cmd.ExecuteScalar(); 
     return result??0; 
    } 
} 

더 좋은 옵션이 모든 코드를 없애 Dapper.Net 같은 마이크로 ORM을 사용하는 것입니다 : 당신은 명령에 대한 연결에게 당신이 그것을 실행할 때마다 첨부 할 수 있습니다 여기

또는

public int[] CheckIDVisitors(string []visitors) 
{ 
    using (var sqlConn=new SqlConnection(Properties.Default.MyDbConnectionString)) 
    { 
     string sql = "SELECT ID FROM Visitors WHERE name IN @names" 
     var results = conn.Query<int?>(sql, new { names = visitors); 
     return results.ToArray(); 
    } 
} 
+0

사실 나는 그 주입을 피하기 위해 sql 매개 변수를 사용하고 있지만 그것은 나를 귀찮게하고 항상 같은 코드를 작성해야합니다. 예를 들어 데이터베이스의 일부 ID를 확인하려면 ID 1, ID 2 및 ID 3을 확인해야합니다. 코드의 동일한 구조를 세 번 작성해야합니다. 그러나이 예제 코드를 사용하여 필자는 필요한 것들을 거기에 넣었고 한 번의 코드 만 작성했습니다. 이 문제를 해결하기위한 제안이 있습니까? 아니면 같은 방법으로하고있다 죄송합니다. 나쁘게도 메소드 이름을 변경하는 것을 잊었습니다. 사실이 코드는 ID 확인과 관련된 많은 것들을 다루어야합니다. –

+0

실행할 * 실제 * 쿼리를 게시하십시오. 보시다시피 원하는 명령을 미리 작성하는 것은 쉽지 않습니다. –

+0

Dapper.Net과 같은 것을 사용하도록 제안 해 주셔서 감사합니다. 아주 도움이 되네 (y) –

관련 문제