Java 删除语句后Spring事务管理回滚
我正在编写一个测试类来测试sql注入攻击的案例。我想使用Spring的事务管理支持。因此我创建了这个基本配置类:Java 删除语句后Spring事务管理回滚,java,spring,Java,Spring,我正在编写一个测试类来测试sql注入攻击的案例。我想使用Spring的事务管理支持。因此我创建了这个基本配置类: @Configuration @EnableTransactionManagement public class Config { @Bean public DataSource dataSource(){ EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
@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()){
您有两个选择:
事务性回调一起使用
DataSourceUtils.getConnection(dataSource)
而不是dataSource.getConnection()
,后者是JdbcTemplate
内部使用的,并且也尊重事务边界。完成后,应调用DataSourceUtils.releaseConnection