问题
below is my ibatis map configuration,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Contact">
<!--- Showing all data of table -->
<select id="getAll" resultClass="com.nik.Contact">
select * from contact
<dynamic prepend="where ">
salary like '%'
<isNotNull property="orderby" >
order by #orderby#, #orderby2#
</isNotNull>
</dynamic>
</select>
</sqlMap>
this is my pojo
package com.nik;
public class Contact {
private String firstName;
private String lastName;
private String email;
private String salary;
private String mobile;
private String orderby;
private String orderby2;
private int id;
public Contact() {}
public Contact(
String firstName,
String lastName,
String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getOrderby() {
return orderby;
}
public void setOrderby(String orderby) {
this.orderby = orderby;
}
public String getOrderby2() {
return orderby2;
}
public void setOrderby2(String orderby2) {
this.orderby2 = orderby2;
}
}
This is my test class,
package com.nik;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import java.io.*;
import java.sql.SQLException;
import java.util.*;
import org.apache.log4j.Logger;
public class IbatisExample{
public static void main(String[] args)
throws IOException,SQLException{
// get a logger instance named "com.foo"
Logger logger = Logger.getLogger("com.nik");
Reader reader = Resources.getResourceAsReader("ibatis-config.xml");
SqlMapClient sqlMap =
SqlMapClientBuilder.buildSqlMapClient(reader);
//Output all contacts
System.out.println("All Contacts");
Contact c1 = new Contact();
c1.setOrderby("salary");
c1.setOrderby2("mobile");
List<Contact> contacts = (List<Contact>)
sqlMap.queryForList("Contact.getAll",c1);
Contact contact = null;
for (Contact c : contacts) {
System.out.print(" " + c.getId());
System.out.print(" " + c.getFirstName());
System.out.print(" " + c.getLastName());
System.out.print(" " + c.getEmail());
System.out.print(" " + c.getSalary());
System.out.print(" " + c.getMobile());
contact = c;
System.out.println("");
}
}
}
The problem here is the order by clause has no effect...
here us output
All Contacts
DEBUG [main] - Created connection 71786792.
DEBUG [main] - {conn-100000} Connection
DEBUG [main] - {pstm-100001} PreparedStatement: select * from contact where salary like '%' order by ?, ?
DEBUG [main] - {pstm-100001} Parameters: [salary, mobile]
DEBUG [main] - {pstm-100001} Types: [java.lang.String, java.lang.String]
DEBUG [main] - {rset-100002} ResultSet
DEBUG [main] - {rset-100002} Header: [id, firstName, lastName, email, salary, mobile]
DEBUG [main] - {rset-100002} Result: [1, abc, 111, abc@hyahoo.com, 5000, 400]
DEBUG [main] - {rset-100002} Result: [2, def, 222, def@yahoo.com, 2000, 100]
DEBUG [main] - {rset-100002} Result: [3, xyz, 333, xyz@yahoo.com, 3000, 300]
DEBUG [main] - Returned connection 71786792 to pool.
1 abc 111 abc@hyahoo.com 5000 400
2 def 222 def@yahoo.com 2000 100
3 xyz 333 xyz@yahoo.com 3000 300
If I change the "#" with "$" in map config (e.g. order by $orderby$, $orderby2$) then it works,
All Contacts
DEBUG [main] - Created connection 71786792.
DEBUG [main] - {conn-100000} Connection
DEBUG [main] - {pstm-100001} PreparedStatement: select * from contact where salary like '%' order by salary, mobile
DEBUG [main] - {pstm-100001} Parameters: []
DEBUG [main] - {pstm-100001} Types: []
DEBUG [main] - {rset-100002} ResultSet
DEBUG [main] - {rset-100002} Header: [id, firstName, lastName, email, salary, mobile]
DEBUG [main] - {rset-100002} Result: [2, def, 222, def@yahoo.com, 2000, 100]
DEBUG [main] - {rset-100002} Result: [3, xyz, 333, xyz@yahoo.com, 3000, 300]
DEBUG [main] - {rset-100002} Result: [1, abc, 111, abc@hyahoo.com, 5000, 400]
DEBUG [main] - Returned connection 71786792 to pool.
2 def 222 def@yahoo.com 2000 100
3 xyz 333 xyz@yahoo.com 3000 300
1 abc 111 abc@hyahoo.com 5000 400
any clue on why inline parameter with # are not working in order by?? I can not use $ as this is as security risk as per fortify 360 :(
回答1:
The $var$
syntax is the only way to tell iBATIS to substitute the value of the var
property as-is into the SQL before the prepared statement is constructed. The reason Fortify warns about it being a security risk is because it can open the door to SQL injection attacks if data that comes directly from an untrusted source is inserted into the SQL as-is with no prior validation.
To prevent such a SQL injection, you could modify your Contact
POJO so that the setOrderBy
and setOrderBy2
methods test their parameters and only allow the object's corresponding attributes to be set if those parameters are within the set of acceptable values. Something like the following:
public void setOrderBy(String orderBy) {
if (orderBy.equals("name") or orderBy.equals(" salary") or orderBy.equals("dept")) {
this.orderBy = orderBy;
} else {
this.orderBy = NULL;
}
}
As long as you validate all of your substitution values like this, it should be perfectly acceptable and safe to use the $var$
syntax.
回答2:
not an elegant solution but I used this as didnt want to do code change,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Contact">
<!--- Showing all data of table -->
<select id="getAll" resultClass="com.nik.Contact" parameterClass="java.util.Map">
select * from contact where salary like '%'
<dynamic prepend="order by">
<isEqual
property="orderby"
compareValue="salary">
salary,
</isEqual>
<isEqual
property="orderby"
compareValue="mobile">
mobile,
</isEqual>
<isEqual
property="orderby2"
compareValue="salary">
salary
</isEqual>
<isEqual
property="orderby2"
compareValue="mobile">
mobile
</isEqual>
</dynamic>
</select>
</sqlMap>
来源:https://stackoverflow.com/questions/12808305/ibatis-inline-parameter-with-in-order-by-clause