Java 删除语句后Spring事务管理回滚

Java 删除语句后Spring事务管理回滚,java,spring,Java,Spring,我正在编写一个测试类来测试sql注入攻击的案例。我想使用Spring的事务管理支持。因此我创建了这个基本配置类: @Configuration @EnableTransactionManagement public class Config { @Bean public DataSource dataSource(){ EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();

我正在编写一个测试类来测试sql注入攻击的案例。我想使用Spring的事务管理支持。因此我创建了这个基本配置类:

@Configuration
@EnableTransactionManagement
public class Config {

    @Bean
    public DataSource dataSource(){
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();

        builder.setType(EmbeddedDatabaseType.H2).addScripts("tables.sql", "import.sql");

        return builder.build();
    }

    @Bean
    public TransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}
当我运行所有测试时,其中一些测试通过了(不应该通过),因为它们看到了其他测试方法的操作结果,我想通过使用事务消除这些操作。我在这里做错了什么吗? 下面我有两个方法。当我运行这两个方法时,如果首先执行sqlInjectionModifyingDatabase,则第二个方法将通过(进入if,它不应该进入),因为从第一个方法删除的所有数据都已提交

@Test
public void sqlInjectionModifyingDatabase() throws SQLException {

    String[] credentials = getInputsWithModification();

    String sql_query = "SELECT 1 FROM CREDENTIALS WHERE user_name = '" + credentials[0]
            + "' AND pass_word = '" + credentials[1]+"'";

    int numOfClientsAfter = 0,numOfClientsBefore = 0;

    try(Connection connection = dataSource.getConnection()){
        ResultSet resultSet = connection.createStatement()
                .executeQuery("SELECT COUNT(*) FROM CREDENTIALS");

        resultSet.next();
        numOfClientsBefore = resultSet.getInt(1);
        System.out.println("Users in the system before executing sql injected query : "
                + numOfClientsBefore);


        dataSource.getConnection().createStatement()
                .executeQuery(sql_query);


        try(ResultSet resultSet2 = connection.createStatement()
                .executeQuery("SELECT COUNT(*) FROM CREDENTIALS")){
            resultSet2.next();
            numOfClientsAfter = resultSet2.getInt(1);
            System.out.println("Users in the system after executing sql injected query : "+ numOfClientsAfter);

        }

    }

    if (numOfClientsAfter != numOfClientsBefore) {
        fail("The number of clients changed.");
    }

}

@Test
public void sqlInjectionSolution() throws SQLException {
    String[] credentials = getInputsWithInjection();

    try(PreparedStatement preparedStatement = dataSource.getConnection()
                        .prepareStatement
                                ("SELECT 1 FROM CREDENTIALS WHERE user_name = ? AND pass_word = ?"))
    {

        preparedStatement.setString(1, credentials[0]);
        preparedStatement.setString(2, credentials[1]);
        ResultSet resultSet = preparedStatement.executeQuery();

        if (!resultSet.next()) {
            System.err.println("Wrong credentials");
            return;
        }

        fail();
        System.out.println("Welcome");

    }



}
测试类别的签名如下:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = Config.class)
@Transactional
public class SqlInjection{...}

是的,问题是,即使您使用的是
@Transactional
,您自己也获得了数据库连接,因此完全绕过了Spring的
@Transactional
支持

   try(Connection connection = dataSource.getConnection()){
您有两个选择:

  • 使用来执行查询,它将参与Spring的事务
  • 事务性回调一起使用
  • 您还可以使用Spring的
    DataSourceUtils.getConnection(dataSource)
    而不是
    dataSource.getConnection()
    ,后者是
    JdbcTemplate
    内部使用的,并且也尊重事务边界。完成后,应调用
    DataSourceUtils.releaseConnection
  • (旁注:我也写了,详细解释了这些不同的模式)。

    欢迎您。介意“接受”答案吗?:)谢谢