结果

  填坑失败,并没有看懂是如何检测sql攻击的。

只能说的是: 建议都使用参数化传递sql语句参数。(所以,用hibernate、mybatis等框架的真不用太担心sql攻击问题。)

前言

本文主要是为了填坑:【spring】jdbcTemplate之sql参数注入

在上文中的demo是:

正确sql:

select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= '1'

攻击sql:

select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= '1';delete from child where child_id='1';--'

执行抛出的异常:

java.sql.SQLException: ORA-00911: 无效字符
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)
at com.vergilyn.test.sh.dao.JdbcTemplateDao.injectionAttack(JdbcTemplateDao.java:49)
at com.lyn.Junit.TestJdbc.testInjectionAttack(TestJdbc.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

最后给出的错误结论:oracle驱动jar中处理对sql注入攻击进行了处理。

为什么会得出错误结论:

1、肯定是技术不过关、分析不仔细。

2、没有严格去验证,单纯的测试了jdbc、jdbcTemplate、Hibernate就得出了此结论。

异常原因:

根据异常提示,我去看了下ojdbc5.jar中的源码。  即核心是oracle/jdbc/driver/T4CMAREngine.class中的unmarshalUB2()、buffer2Value(byte var)。

主要是在buffer2Value()方法返回long的值是911,然后ojdbc在后面根据此值抛出以上异常。

表示实在看不懂buffer2Value()及其内部含义,但简单理解就是在攻击sql中出现了”;”分号,导致抛出此异常。

一、验证非参数话会存在sql注入攻击(jdbcTemplate测试)

    @Test
@Rollback()
public void testSqlInjectionAttack(){ //结论: jdbcTemplate不用参数化会存在sql攻击问题。
String id = "1"; //正确参数
// id = "1' or 1=1 --"; //sql攻击参数
Object rs = jdbcDao.sqlInjectionAttack(id);
System.out.println(JSON.toJSONString(rs));
}
  public Object sqlInjectionAttack(String id){
String sql = "select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c";
sql += " where c.child_id= '"+id+"'";
return this.jdbcTemplate.query(sql,new BeanPropertyRowMapper<Child>(Child.class));
}

说明:1、正确的是返回一个Child对象。攻击sql则返回List<Child>对象。

2、用的方法是query(…)。如果是queryForXXX(…),可能会抛异常:org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 10

sql攻击结果:

二、验证参数化查询防止sql注入攻击

    @Test
@Rollback()
public void solveSqlInjectionAttack(){ //参数化sql防止sql注入攻击
String id = "1"; //正确参数
// id = "1' or 1=1 --"; //sql攻击参数
Object rs = jdbcTemplateDao.solveSqlInjectionAttack(id);
System.out.println(JSON.toJSONString(rs));
}
  public Object solveSqlInjectionAttack(String id){
String sql = "select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c";
sql += " where c.child_id= ?";
return this.jdbcTemplate.query(sql,new Object[]{id},new BeanPropertyRowMapper<Child>(Child.class));
}

正确sql结果:

攻击sql结果:

信息: Rolled back transaction for test context [DefaultTestContext@1cfddcd testClass = JdbcTemplateTest, testInstance = com.vergilyn.persistence.test.jdbcTemplate.JdbcTemplateTest@1ead226, testMethod = solveSqlInjectionAttack@JdbcTemplateTest, testException = org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= ?]; ORA-01722: 无效数字
; nested exception is java.sql.SQLException: ORA-01722: 无效数字
, mergedContextConfiguration = [MergedContextConfiguration@18add92 testClass = JdbcTemplateTest, locations = '{classpath:jdbcTemplate/jdbcTemplate-context.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]. 十二月 31, 2016 12:42:03 上午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.support.GenericApplicationContext@1f12030: startup date [Sat Dec 31 00:41:44 CST 2016]; root of context hierarchy org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select c.child_id childId,c.child_name,c.child_age childAge,c.parent_id parentId from child c where c.child_id= ?]; ORA-01722: 无效数字
; nested exception is java.sql.SQLException: ORA-01722: 无效数字
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:243)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:695)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:727)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:737)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:787)
at com.vergilyn.persistence.jdbcTemplate.JdbcTemplateDao.solveSqlInjectionAttack(JdbcTemplateDao.java:42)
at com.vergilyn.persistence.test.jdbcTemplate.JdbcTemplateTest.solveSqlInjectionAttack(JdbcTemplateTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
Caused by: java.sql.SQLException: ORA-01722: 无效数字 at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:703)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:644)
... 34 more

异常信息

以上结果是因为,数据库中的CHILD_ID的类型是NUMBER,传入的参数却是String。

当我把CHILD_ID的类型修改为:varchar2时,sql可正常执行。但sql查询结果是null。因为,数据库记录中并没有一个CHILD_ID = ”1' or 1=1 --“

三、部分源码 (填坑失败,后面的代码逻辑实在难看懂。)

       /**
* Query using a prepared statement, allowing for a PreparedStatementCreator
* and a PreparedStatementSetter. Most other query methods use this method,
* but application code will always work with either a creator or a setter.
* @param psc Callback handler that can create a PreparedStatement given a
* Connection
* @param pss object that knows how to set values on the prepared statement.
* If this is null, the SQL will be assumed to contain no bind parameters.
* @param rse object that will extract results.
* @return an arbitrary result object, as returned by the ResultSetExtractor
* @throws DataAccessException if there is any problem
*/
public <T> T query(
PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
throws DataAccessException { Assert.notNull(rse, "ResultSetExtractor must not be null");
logger.debug("Executing prepared SQL query"); return execute(psc, new PreparedStatementCallback<T>() { //line:695
@Override
public T doInPreparedStatement(PreparedStatement ps) throws SQLException {
ResultSet rs = null;
try {
if (pss != null) {
pss.setValues(ps);
}
rs = ps.executeQuery(); // 抛出异常方法 - 02 ResultSet rsToUse = rs;
if (nativeJdbcExtractor != null) {
rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
}
return rse.extractData(rsToUse);
}
finally {
JdbcUtils.closeResultSet(rs);
if (pss instanceof ParameterDisposer) {
((ParameterDisposer) pss).cleanupParameters();
}
}
}
});
}
            //-------------------------------------------------------------------------
// Methods dealing with prepared statements
//-------------------------------------------------------------------------
@Override
public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
throws DataAccessException { Assert.notNull(psc, "PreparedStatementCreator must not be null");
Assert.notNull(action, "Callback object must not be null");
if (logger.isDebugEnabled()) {
String sql = getSql(psc);
logger.debug("Executing prepared SQL statement" + (sql != null ? " [" + sql + "]" : ""));
} Connection con = DataSourceUtils.getConnection(getDataSource());
PreparedStatement ps = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
ps = psc.createPreparedStatement(conToUse);
applyStatementSettings(ps);
PreparedStatement psToUse = ps;
if (this.nativeJdbcExtractor != null) {
psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
}
T result = action.doInPreparedStatement(psToUse); // 抛出异常方法 - 01
handleWarnings(ps);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
if (psc instanceof ParameterDisposer) {
((ParameterDisposer) psc).cleanupParameters();
}
String sql = getSql(psc);
psc = null;
JdbcUtils.closeStatement(ps);
ps = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("PreparedStatementCallback", sql, ex); //line: 660
}
finally {
if (psc instanceof ParameterDisposer) {
((ParameterDisposer) psc).cleanupParameters();
}
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}

其中抛异常的方法是: at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:660)

方法中的>>>> T result = action.doInPreparedStatement(psToUse);

此处的action.doInPreparedStatement(psToUse)实际调用的就是上面 - 匿名内部类中定义的。

// 抛出异常 - 02 代码
public ResultSet executeQuery() throws SQLException {
this.checkOpen();
try {
return DelegatingResultSet.wrapResultSet(this, ((PreparedStatement)this._stmt).executeQuery());
} catch (SQLException var2) {
this.handleException(var2);
throw new AssertionError();
}
}

出现异常方法:((PreparedStatement)this._stmt).executeQuery()。  this._stmt = OraclePreparedStatementWrapper.class

// OraclePreparedStatementWrapper.class
public ResultSet executeQuery() throws SQLException {
return this.preparedStatement.executeQuery(); //this.preparedStatement = T4CPreparedStatement.class
}
class T4CPreparedStatement extends OraclePreparedStatement;  
// OraclePreparedStatement.classpublic ResultSet executeQuery() throws SQLException {
PhysicalConnection var1 = this.connection;
synchronized(this.connection) {
this.executionType = 1;
this.executeInternal(); // 异常方法 - 03
if(this.userRsetType == 1) {
this.currentResultSet = new OracleResultSetImpl(this.connection, this);
return this.currentResultSet;
} else {
if(this.scrollRset == null) {
this.currentResultSet = new OracleResultSetImpl(this.connection, this);
this.scrollRset = this.currentResultSet;
}
return this.scrollRset;
}
}
} int executeInternal() throws SQLException {
this.noMoreUpdateCounts = false;
this.ensureOpen();
if(this.currentRank > 0 && this.m_batchStyle == 2) {
SQLException var3 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 81, "batch must be either executed or cleared");
var3.fillInStackTrace();
throw var3;
} else {
boolean var1 = this.userRsetType == 1;
this.prepareForNewResults(true, false);
this.processCompletedBindRow(this.sqlKind == 0?1:this.batch, false);
if(!var1 && !this.scrollRsetTypeSolved) {
return this.doScrollPstmtExecuteUpdate() + this.prematureBatchCount;
} else {
this.doExecuteWithTimeout(); // 异常方法 - 04
boolean var2 = this.prematureBatchCount != 0 && this.validRows > 0;
if(!var1) {
this.currentResultSet = new OracleResultSetImpl(this.connection, this);
this.scrollRset = ResultSetUtil.createScrollResultSet(this, this.currentResultSet, this.realRsetType);
if(!this.connection.accumulateBatchResult) {
var2 = false;
}
} if(var2) {
this.validRows += this.prematureBatchCount;
this.prematureBatchCount = 0;
} return this.validRows;
}
}
}
void doExecuteWithTimeout() throws SQLException {
try {
this.cleanOldTempLobs();
this.connection.registerHeartbeat();
this.rowsProcessed = 0;
SQLException var1;
if(this.sqlKind == 0) {
if(this.connection.j2ee13Compliant && this.executionType == 2) {
var1 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 129);
var1.fillInStackTrace();
throw var1;
} this.connection.needLine();
if(!this.isOpen) {
this.connection.open(this);
this.isOpen = true;
} if(this.queryTimeout != 0) {
try {
this.connection.getTimeout().setTimeout((long)(this.queryTimeout * 1000), this);
this.executeMaybeDescribe();
} finally {
this.connection.getTimeout().cancelTimeout();
}
} else {
this.executeMaybeDescribe(); // 异常方法 - 05
} this.checkValidRowsStatus();
if(this.serverCursor) {
this.adjustGotLastBatch();
}
} else {
if(this.connection.j2ee13Compliant && this.sqlKind != 1 && this.sqlKind != 4 && this.executionType == 1) {
var1 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), 128);
var1.fillInStackTrace();
throw var1;
} ++this.currentRank;
if(this.currentRank >= this.batch) {
try {
this.connection.needLine();
if(!this.isOpen) {
this.connection.open(this);
this.isOpen = true;
} if(this.queryTimeout != 0) {
this.connection.getTimeout().setTimeout((long)(this.queryTimeout * 1000), this);
} this.isExecuting = true;
this.executeForRows(false);
} catch (SQLException var14) {
this.needToParse = true;
if(this.batch > 1) {
this.clearBatch();
int[] var2;
int var3;
if(this.numberOfExecutedElementsInBatch != -1 && this.numberOfExecutedElementsInBatch < this.batch) {
var2 = new int[this.numberOfExecutedElementsInBatch]; for(var3 = 0; var3 < var2.length; ++var3) {
var2[var3] = -2;
}
} else {
var2 = new int[this.batch]; for(var3 = 0; var3 < var2.length; ++var3) {
var2[var3] = -3;
}
} BatchUpdateException var17 = DatabaseError.createBatchUpdateException(var14, var2.length, var2);
var17.fillInStackTrace();
throw var17;
} this.resetCurrentRowBinders();
throw var14;
} finally {
if(this.queryTimeout != 0) {
this.connection.getTimeout().cancelTimeout();
} this.currentRank = 0;
this.isExecuting = false;
this.checkValidRowsStatus();
}
}
}
} catch (SQLException var16) {
this.resetOnExceptionDuringExecute();
throw var16;
} this.connection.registerHeartbeat();
}
void executeMaybeDescribe() throws SQLException
{
int i = 1;
if (this.rowPrefetchChanged)
{
if ((this.streamList == null) && (this.rowPrefetch != this.definesBatchSize)) {
this.needToPrepareDefineBuffer = true;
}
this.rowPrefetchChanged = false;
} if (!this.needToPrepareDefineBuffer)
{
if (this.accessors == null)
{
this.needToPrepareDefineBuffer = true;
} else if (this.columnsDefinedByUser) {
this.needToPrepareDefineBuffer = (!checkAccessorsUsable());
}
}
boolean bool = false;
try
{
this.isExecuting = true;
if (this.needToPrepareDefineBuffer)
{
if (!this.columnsDefinedByUser)
{
executeForDescribe();// 异常方法 – 06 实际是调用T4CPreparedStatement.class中的实现方法
bool = true;
if (this.aFetchWasDoneDuringDescribe) {
i = 0;
}
}
if (this.needToPrepareDefineBuffer)
{
prepareAccessors();
}
} int j = this.accessors.length;
for (int k = this.numberOfDefinePositions; k < j; k++)
{
Accessor localAccessor = this.accessors[k];
if (localAccessor != null)
localAccessor.rowSpaceIndicator = null;
}
if (i != 0) {
executeForRows(bool);
}
}
catch (SQLException localSQLException)
{
this.needToParse = true;
throw localSQLException;
}
finally
{
this.isExecuting = false;
}
}
// T4CPreparedStatement.class
void executeForDescribe() throws SQLException {
this.t4Connection.assertLoggedOn("oracle.jdbc.driver.T4CPreparedStatement.execute_for_describe");
this.cleanOldTempLobs(); try {
if(this.t4Connection.useFetchSizeWithLongColumn) {
this.doOall8(true, true, true, true, false);
} else {
this.doOall8(true, true, false, true, this.definedColumnType != null);// 异常 - 07
}
} catch (SQLException var8) {
throw var8; // ORA-01722: 无效数字 } catch (IOException var9) {            ((T4CConnection)this.connection).handleIOException(var9);            SQLException var2 = DatabaseError.createSqlException(this.getConnectionDuringExceptionHandling(), var9);            var2.fillInStackTrace();            throw var2;        } finally {            this.rowsProcessed = this.t4Connection.all8.rowsProcessed;            this.validRows = this.t4Connection.all8.getNumRows();        }        this.needToParse = false;        this.implicitDefineForLobPrefetchDone = false;        this.aFetchWasDoneDuringDescribe = false;        if(this.t4Connection.all8.aFetchWasDone) {            this.aFetchWasDoneDuringDescribe = true;            this.rowPrefetchInLastFetch = this.rowPrefetch;        }        for(int var1 = 0; var1 < this.numberOfDefinePositions; ++var1) {            this.accessors[var1].initMetadata();        }        this.needToPrepareDefineBuffer = false;    }

【spring】(填坑)sql注入攻击 - 持久层参数化的更多相关文章

  1. Spring MVC 如何防止XSS、SQL注入攻击

    在Web项目中,通常需要处理XSS,SQL注入攻击,解决这个问题有两个思路: 在数据进入数据库之前对非法字符进行转义,在更新和显示的时候将非法字符还原 在显示的时候对非法字符进行转义 如果项目还处在起 ...

  2. SQL注入攻击

    SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候, ...

  3. 如何对抗、预防 SQL注入 攻击

    一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...

  4. JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务

    JDBC基础 重难点梳理 一.JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以 ...

  5. Java程序员从笨鸟到菜鸟之(一百零二)sql注入攻击详解(三)sql注入解决办法

    sql注入攻击详解(二)sql注入过程详解 sql注入攻击详解(一)sql注入原理详解 我们了解了sql注入原理和sql注入过程,今天我们就来了解一下sql注入的解决办法.怎么来解决和防范sql注入, ...

  6. 防止SQL注入攻击的一些方法小结

    SQL注入攻击的危害性很大.在讲解其防止办法之前,数据库管理员有必要先了解一下其攻击的原理.这有利于管理员采取有针对性的防治措施. 一. SQL注入攻击的简单示例. statement := &quo ...

  7. php安全编程—sql注入攻击

    php安全编程--sql注入攻击 定义 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因 ...

  8. SQL注入攻击[详解]

    SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候, ...

  9. 【渗透攻防WEB篇】SQL注入攻击初级

    前言不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动.在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一,这里我想问 ...

随机推荐

  1. pyinstaller相关问题 & pygame文件打包成exe文件 & 武装飞船 & 飞机大战

    自己照书写了一个飞机大战游戏的python程序,想把它打包成一个exe文件,在查阅相关教程并经过数次尝试后终于成功. 安装打包应用 pyinstaller 在cmd命令窗口下pip install p ...

  2. 第3章 JDK并发包(一)

    3.1 多线程的团队协作:同步控制 3.1.1 synchronized的功能扩展:重入锁 重入锁可以完全替代synchronized关键字. 重入锁使用java.util.concurrent.lo ...

  3. linux下安装php的svn模块

    在php下为了方便使用svn命令,还是安装下php的svn扩展 首先确保机器上已经有lamp或lnmp环境,然后 >yum install subversion subversion-devel ...

  4. python 中列表 元组 字典 集合的区别

    先看图片解释 (1)列表 什么是列表呢?我觉得列表就是我们日常生活中经常见到的清单.比如,统计过去一周我们买过的东西,把这些东西列出来,就是清单.由于我们买一种东西可能不止一次,所以清单中是允许有重复 ...

  5. JS设计模式——策略模式

    设计模式高大上,业务代码用不上...平时用不上我们就可以忽略了吗? 非也,就像面试造火箭,工作拧螺丝一样.万一我们公司哪天要造火箭了,你得立马能上手. 同时,有些复杂的业务代码也可以用设计模式的思想去 ...

  6. CVE-2020-0618 SQL 远程代码执行

    CVE-2020-0618 SQL Server远程代码执行 1.简介 SQL Server Reporting Services(SSRS)提供了一组本地工具和服务,用于创建,部署和管理移动报告和分 ...

  7. axios中qs的使用

    首先qs是一个npm仓库所管理的包,可通过npm install qs命令进行安装. 地址: https://www.npmjs.com/package/qs qs.parse().qs.string ...

  8. 分享下超实用的用skura frp做内网穿透的经验

    操作目的: 使无公网ip的主机能被外网访问,实现ssh对服务器的远程管理 硬件准备: 1.服务端:skura frp主机(skura frp 免费提供,有待创建) 2.客户端:接在无线路由器(内网)上 ...

  9. $.getJSON获取json数据失败

    首先简单介绍下 $.ajax  $.get  $.post  $.getJSON 的区别和用法 $.ajax中有一个type属性,专门用来指定是get请求还是post请求的分别对应的就是$.get和$ ...

  10. 12-Factor与云原生Part2

    12-Factor与云原生Part2 12-Factor 为构建如下的 SaaS 应用提供了方法论: 使用声明式格式来搭建自动化,从而使新的开发者花费最少的学习成本加入这个项目 和底层操作系统保持简洁 ...