2017-08-08 49 views
0

我正在使用prepareStatement()來防止sql注入。我現在遇到的問題是用下面的方法,我可以做getConnection().prepareStatement()然後建立我的查詢,但是我需要嘗試每次調用getConnection()並在finally區塊中關閉它。 createStatement().execute()似乎更好,因爲我可以讓客戶端傳遞查詢,然後在一個地方處理try-catch-finally,但它不會阻止SQL注入。通常最好的做法是什麼?或者是否有任何其他方式來構建可以防止SQL注入的查詢?在處理jdbc時關閉連接的最佳實踐是什麼

private static Connection getConnection() throws SQLException, URISyntaxException { 
    URI dbUri = new URI(System.getenv("DATABASE_URL")); 

    String username = dbUri.getUserInfo().split(":")[0]; 
    String password = dbUri.getUserInfo().split(":")[1]; 
    String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath(); 

    return DriverManager.getConnection(dbUrl, username, password); 
} 
+4

您應該使用經過充分驗證的連接池,而不是創建自己的。檢出連接,將它傳遞給數據訪問對象,關閉finally塊中方法範圍內的所有其他JDBC資源,然後將連接返回到池 – duffymo

+0

@duffymo我不太明白。這是我第一次在服務器端寫Java。請問您可以提供一些示例 – user1865027

+0

您會將您的應用程序部署到什麼地方? Tomcat的?春季啓動? JBOSS?所有內置連接池。我建議使用它們。 – duffymo

回答

1

我會使用連接池,而不是每次創建連接和關閉。

夫婦的,我們應該遵循創建使用Tomcat服務器

步驟連接池-1步驟。

<?xml version='1.0' encoding='utf-8'?> 
... 
    <GlobalNamingResources> 
    ... 
    <Resource name="jdbc/JCGExampleDB" 
       global="jdbc/JCGExampleDB" 
       factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
       auth="Container" 
       type="javax.sql.DataSource"    
       username="test" 
       password="test" 
       driverClassName="com.mysql.jdbc.Driver" 
       description="JCG Example MySQL database." 
       url="jdbc:mysql://localhost:3306/JCGExampleDB" 
       maxTotal="10" 
       maxIdle="10" 
       maxWaitMillis="10000" 
       removeAbandonedTimeout="300"    
       defaultAutoCommit="true" /> 
    ... 
    </GlobalNamingResources> 

步驟-2: - 你可以寫你的數據庫連接工具類的得到這樣的連接 使用Spring的JdbcTemplate與數據庫連接的細節,如下面更新TOMCAT_ROOT_DIR \ conf \ server.xml文件下面(該步驟可以以多種方式來完成..像context.xml文件或web.xml文件或如下)

@Bean 
    public JdbcTemplate jdbcTemplate() { 
     return new JdbcTemplate(dataSource()); 
    } 

    @Bean 
    public DataSource dataSource() { 
     DataSource dataSource = new com.mchange.v2.c3p0.ComboPooledDataSource(); 
     try { 
      JndiTemplate jndiTemplate = new JndiTemplate(); 
      dataSource = (DataSource)jndiTemplate.lookup("java:comp/env/jdbc/JCGExampleDB"); 
      } catch (NamingException e) { 
      log.error("Unable to configure datasource: " + e.getStackTrace()); 
     } 
     return dataSource; 
    } 

EDIT1: 使用S ingleton類 - 沒有JdbcTemplate:你可以在需要時從Singleton類獲得連接。

public class DatabaseConnectionManager { 

    DataSource ds; 

    public void init() { 
     InitialContext initialContext = new InitialContext(); 
     ds = (javax.sql.DataSource)initialContext.lookup("jdbc/JCGExampleDB"); 
    } 

    public Connection getConnection() { 
     if(ds == null) init(); 

     return ds.getConnection(); 
    } 
} 

希望這有助於...

+0

我喜歡你對JdbcTemplate的建議,但應該指出,如果OP使用Spring,它纔有意義。 – duffymo

+0

即時通訊不使用春天。並且我實際上並不瞭解在您的示例中連接如何正確關閉。我是否仍然需要在每次撥打電話時手動關閉它 – user1865027

+0

@ user1865027 - 我更新了答案,而不使用Spring。如果您使用連接池,那麼池將根據您在標記中提到的參數來打開和關閉連接。 –