How do I filter single quotes ' in java?
I have a search box where if anyone types a single quote, I get a database error.
I don't want to filet it in JavaScript or at Database level; I want to do it in Java only. How can I do that?
I don't want to lose it completely. Is there any other way? Will replacing the quote with \' work??
I think you're approaching the problem from the wrong angle. I strongly suspect you're building your SQL like this:
String sql = "SELECT * FROM TABLE WHERE USERID='" + userInput + "'";
or something similar. Don't do that. Use a parameterized query instead, and supply the user input as the parameter. Every database I've ever used knows how to handle that, and it's the safe way to handle user input.
If you really, really just want to get rid of quotes, you can use:
text = text.replace("'", "");
... but please don't. Use a parameterized query instead.
Yes, use PreparedStatement.setString():
String sql = "SELECT * FROM table WHERE USERID = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, "O'Connor");
ResultSet rs = pstmt.executeQuery();
Escaping rules for databases differ. For example in Oracle you can duplicate the apostrope to get it escaped. In MySQL it is backslash + apostrophe (I think).
So either userInput = userInput.replaceAll("'", "''"); or userInput = userInput.replaceAll("'", "\\'");
Related
I was wondering if there was any way to specify returned column names using prepared statements.
I am using MySQL and Java.
When I try it:
String columnNames="d,e,f"; //Actually from the user...
String name = "some_table"; //From user...
String query = "SELECT a,b,c,? FROM " + name + " WHERE d=?";//...
stmt = conn.prepareStatement(query);
stmt.setString(1, columnNames);
stmt.setString(2, "x");
I get this type of statement (printing right before execution).
SELECT a,b,c,'d,e,f' FROM some_table WHERE d='x'
I would, however, like to see:
SELECT a,b,c,d,e,f FROM some_table WHERE d='x'
I know that I cannot do this for table names, as discussed
here, but was wondering if there was some way to do it for column names.
If there is not, then I will just have to try and make sure that I sanitize the input so it doesn't lead to SQL injection vulnerabilities.
This indicates a bad DB design. The user shouldn't need to know about the column names. Create a real DB column which holds those "column names" and store the data along it instead.
And any way, no, you cannot set column names as PreparedStatement values. You can only set column values as PreparedStatement values
If you'd like to continue in this direction, you need to sanitize the column names (to avoid SQL Injection) and concatenate/build the SQL string yourself. Quote the separate column names and use String#replace() to escape the same quote inside the column name.
Prepare a whitelist of allowed column names. Use the 'query' to look up in the whitelist to see if the column name is there. If not, reject the query.
For MySQL prepared statements with NodeJS (mysqljs/mysql), what you need to know is that ? is for values, but if you need to escape column names, table names etc, use ?? instead.
Something like this will work:
SELECT ??, ??, ?? FROM ?? WHERE ?? < ?
Set values to ['id', 'name', 'address', 'user', 'id', 100]
I think this case can't work because the whole point of the prepared statement is to prevent the user from putting in unescaped query bits - so you're always going to have the text quoted or escaped.
You'll need to sanitize this input in Java if you want to affect the query structure safely.
Use sql injection disadvantage of Statement Interface as advantage.
Ex:
st=conn.createStatement();
String columnName="name";
rs=st.executeQuery("select "+ columnName+" from ad_org ");
public void MethodName(String strFieldName1, String strFieldName2, String strTableName)
{
//Code to connect with database
String strSQLQuery=String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);
st=conn.createStatement();
rs=st.executeQuery(strSQLQuery);
//rest code
}
Below is the solution in java.
String strSelectString = String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);
My query
attributes.replace(" ' ", "");
//also used SET "+attributes+"
String sql;
sql = "UPDATE diseaseinfo"
+ " SET ?=?"
+ "WHERE companyname = 'mycom' && diseaseName =?";
PreparedStatement preparedStmt = connects.prepareStatement(sql);
preparedStmt.setString(1, attributes);
preparedStmt.setString(2, attrData);
preparedStmt.setString(3, medname);
System.out.println(preparedStmt);
it is giving me an error because query set the column name in string so it become like this on causes
UPDATE diseaseinfo SET 'causes'='abc' WHERE companyname = 'mycom' and diseaseName ='fever'
and through this question I get to know that I can't add dynamic column by prepared statement: https://stackoverflow.com/a/3136049/7794329
Now, the real question comes up: suppose if I will use a simple update query like in this question: jdbc dymanic sql query with variable containg 's
It says you can't enter value with 's in your simple sql query because it will again make the query syntactical error for example :
SELECT * FROM diseaseinfo WHERE diseaseName = 'Adult Still's disease' AND name = 'add';
Here it wont execute because of ' 's on 'Adult Still's
Then it won't work with simple query. What should I do now? What to use? To set dynamic column with taking care of 's in the query.
I am not worried about SQL injection because i am working on local. And I just want my query to be executed.
Right. We can't supply identifiers as bind parameters. The name of the column has to be part of the SQL text.
We can dynamically incorporate the name of the column into the SQL text with something like this:
sql = "UPDATE diseaseinfo"
+ " SET `" + colname + "` = ?"
+ " WHERE companyname = 'mycom' AND diseaseName = ?";
And supply values for the two remaining bind parameters
preparedStmt.setString(1, attrData);
preparedStmt.setString(2, medname);
And you are absolutely correct about being concerned about SQL Injection.
Supplied as bind values, single quotes in the values of attrData and medname won't be an issue, in terms of SQL Injection.
But the example I've provided is vulnerable through incorporating the colname variable into the SQL text, if we don't have some guaranteed that colname is "safe" to include in the statement.
So we need to make the assignment of a value to colname "safe".
Several approaches we can use do that. The most secure would be a "whitelist" approach. The code can ensure that only specific allowed "safe" values get assigned to colname, before colname gets included into the SQL text.
As a simple example:
String colname;
if (attributes.equals("someexpectedvalue") {
colname = "columnname_to_be_used";
} else if (attributes.equals("someothervalid") {
colname = "valid_columname";
} else {
// unexpected/unsupported attributes value so
// handle condition or throw an exception
}
A more flexible approach is to ensure that a backtick character doesn't appear in colname. In the example, the value of colname is being escaped by enclosing it in backticks. So, as long as a backtick character doesn't appear in colname, we will prevent a supplied value from being interpreted as anything other than as an identifier.
For a more generic (and complicated) approach to using hardcoded backtick characters, we could consider making use the supportsQuotedIdentifiers and getIdentifierQuoteString methods of java.sql.DatabaseMetaData class.
(In the OP code, we don't see the datatype of contents of attributes. We see a call to a method named replace, and the arguments that are supplied to that. Assuming that attributes is a String, and that's supposed to be a column name, it's not at all clear why we would have "space single quote space" in the string, or why we need to remove that. Other than this mention, this answer doesn't address that.)
I have a bean class which does maintain user data:
soppose I have created a postgresql DB table like this:
StringBuffer sqlStr = new StringBuffer();
sqlStr.append("CREATE TABLE Users ("
user_id bigint,
username character varying NOT NULL,
biography character varying NOT NULL
);
& I want to make a query command and inject my String data inside it:
sqlStr.append("INSERT INTO users(" +
"user_id, username, biography)" +
"\n\tVALUES (" + user.getID()+ "," + user.getUsername() + "," + user.getBiography()+");";
my problem is for example if the data coming from my method has quote or double quote or "," my command will become wrong suppose that the user biography is something like this :
hello, I'm Mr X an "IT Pro" ...
If I run my application and save the output inside a file called query.sql I can't use it because my query command is wrong because of quote & double quote, something like this:
INSERT INTO users(userid, username, biography)
VALUES(2, 'Mehdi', 'hello, I'm Mr X an "IT Pro" ..');
how Can I fix this problem ?
You should never ever use the above method for constructing SQL queries.
"Why not?" you ask, well; where to start. The classic example is Bobby Tables, the more general problem is SQL injection. This leaves your program open to attack but also to random failure - like the situation you describe.
Now, the solution. Always use PreparedStatement to construct your query. In your example
final String query = "INSERT INTO users(user_id, username, biography) VALUES (?,?,?)";
final PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, user.getID());
ps.setString(2, user.getUsername());
ps.setString(3, user.getBiography());
ps.executeUpdate();
A much nicer syntax to use with is the the SET syntax rather than the traditional VALUES syntax. The query would then look like
final String query = "INSERT INTO users SET user_id = ?, username = ?, biography = ?";
EDIT
The OP is building a query for a script file, not executing a query in the code.
There is a utility class in Apache Commons Lang, StringEscapeUtils. This has an escapeSql method. Looking at the source code, all this does is escape single quotes with another single quote.
This works if you build your queries with single quotes:
VALUES (" + user.getID()+ ",'" + user.getUsername() + "'...
So the query, once the example value is inserted will go from:
VALUES (10 ,'hello, I'm Mr X an "IT Pro"'...
Will become
VALUES (10 ,'hello, I''m Mr X an "IT Pro"'...
The apostrophe in "I'm" is now escaped and harmless.
Note that you obviously need to escape the values and not the query, so (assuming you have a static import for the class)
VALUES (" + user.getID()+ ",'" + escapeSql(user.getUsername()) + "'...
But does not escape other sql characters, percent signs for example.
This is really a stop-gap measure to make the code work while you come up with a more robust solution. And you should come up with a more robust solution.
Why dont you use PreparedStatement? That will also give you better performance as the SQL will be pre-compiled on DB side.
Or
You can escape the quotes using
String.replaceAll http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replaceAll(java.lang.String, java.lang.String)
I can't find the correct syntax of the following query in java,please help me.
String st = "SELECT COUNT('"+id+"') FROM '"+selected_table+"' ";
String st = "SELECT COUNT('"+id+"') FROM '"+selected_table+"'";
I think that the mistake is how to end the query...
Since I got the error Check the manual that corresponds to your MySQL server version for the right syntax to use near ''Customer'' at line 1
when I choose Customer table
You want to use backticks instead of single quotes around your object names.
String st = "SELECT COUNT(`"+id+"`) FROM `"+selected_table+"` ";
Table names should be surrounded by tick marks (`), not single quotes (')
String st = "SELECT COUNT('"+id+"') FROM `"+selected_table+"`";
^ use tick marks ^
What are the values of id and selected_table? What is the actual query string that is sent to the database?
Also, it's rarely a good idea to manually build a query like this using string concatenation. This makes it very easy for a bug to result in a gaping security hole, and it's a lot more difficult (and risky) to try to secure this approach than it is to just do it right.
Looks from your query that you are enclosing your id and selected_table in single quotes... For example, SELECT COUNT('ID') FROM 'CUSTOMER' which is wrong. should be in backtics `` or nothing...
I was wondering if there was any way to specify returned column names using prepared statements.
I am using MySQL and Java.
When I try it:
String columnNames="d,e,f"; //Actually from the user...
String name = "some_table"; //From user...
String query = "SELECT a,b,c,? FROM " + name + " WHERE d=?";//...
stmt = conn.prepareStatement(query);
stmt.setString(1, columnNames);
stmt.setString(2, "x");
I get this type of statement (printing right before execution).
SELECT a,b,c,'d,e,f' FROM some_table WHERE d='x'
I would, however, like to see:
SELECT a,b,c,d,e,f FROM some_table WHERE d='x'
I know that I cannot do this for table names, as discussed
here, but was wondering if there was some way to do it for column names.
If there is not, then I will just have to try and make sure that I sanitize the input so it doesn't lead to SQL injection vulnerabilities.
This indicates a bad DB design. The user shouldn't need to know about the column names. Create a real DB column which holds those "column names" and store the data along it instead.
And any way, no, you cannot set column names as PreparedStatement values. You can only set column values as PreparedStatement values
If you'd like to continue in this direction, you need to sanitize the column names (to avoid SQL Injection) and concatenate/build the SQL string yourself. Quote the separate column names and use String#replace() to escape the same quote inside the column name.
Prepare a whitelist of allowed column names. Use the 'query' to look up in the whitelist to see if the column name is there. If not, reject the query.
For MySQL prepared statements with NodeJS (mysqljs/mysql), what you need to know is that ? is for values, but if you need to escape column names, table names etc, use ?? instead.
Something like this will work:
SELECT ??, ??, ?? FROM ?? WHERE ?? < ?
Set values to ['id', 'name', 'address', 'user', 'id', 100]
I think this case can't work because the whole point of the prepared statement is to prevent the user from putting in unescaped query bits - so you're always going to have the text quoted or escaped.
You'll need to sanitize this input in Java if you want to affect the query structure safely.
Use sql injection disadvantage of Statement Interface as advantage.
Ex:
st=conn.createStatement();
String columnName="name";
rs=st.executeQuery("select "+ columnName+" from ad_org ");
public void MethodName(String strFieldName1, String strFieldName2, String strTableName)
{
//Code to connect with database
String strSQLQuery=String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);
st=conn.createStatement();
rs=st.executeQuery(strSQLQuery);
//rest code
}
Below is the solution in java.
String strSelectString = String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName);