2011-09-21 47 views
2

我的应用程序当前利用SQLite数据库来存储用户的消息。但是,如果用户在任何字段中输入撇号,则数据库会崩溃。我意识到这个问题是由于SQLite使用撇号作为引号分隔符(我在存储的消息文本周围放置了单个撇号),但想不到任何好的解决方法。在SQLite数据库中存储带有撇号的字符串的常见做法是什么?用户输入撇号崩溃Android应用程序(SQL相关)

这是我收到一个错误的一个例子:

java.lang.RuntimeException: Unable to resume activity {x.x.x.x/x.x.x.x.Main}: android.database.sqlite.SQLiteException: near "m": syntax error: , while compiling: SELECT title, contact_name, contact_number FROM contacts WHERE title='I'm at work' 
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3128) 
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3143) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2684) 
at android.app.ActivityThread.access$2300(ActivityThread.java:125) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:123) 
at android.app.ActivityThread.main(ActivityThread.java:4627) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:521) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:859) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:617) 
at dalvik.system.NativeStart.main(Native Method) 
Caused by: android.database.sqlite.SQLiteException: near "m": syntax error: , while compiling: SELECT title, contact_name, contact_number FROM contacts WHERE title='I'm at work' 
at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method) 
at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:91) 
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:64) 
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:80) 
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:46) 
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42) 
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1454) 
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1338) 
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1293) 
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1373) 
... 19 more 

回答

10

this的问题 - 有好几个答案应该帮助你。

它具体地讲述使用DatabaseUtils.sqlEscapeString或:

uservalue = getText().tostring(); 
uservalue = uservalue.replace("'","\'"); 
//execute query... 
+0

感谢您的链接。我到处搜索了一个类似的问题,但我正在搜索“撇号”而不是“单引号”。 –

+0

真棒:)没问题 - 这upvote标记我> 2000代表标记。 Woohooo。 – Jack

+2

DatabaseUtils.sqlEscapeString对我来说是最简单的解决方案,FTW –

3

通用数据库的准则(和安全编码指南)帮助prvent针对这一点,因为这是造成你的错误一样的东西可以为SQL注入攻击所利用。最常见的防御(每OWASP准则优先顺序排列):

  1. 使用parmeterized存储过程
  2. 使用参数化查询,如果数据库引擎支持它。
  3. 作为最后的手段,逃避串(实施dependednt数据库引擎。)

SQLLite支持选项2和3

从这个页面:http://www.sqlite.org/lang_expr.html

的字符串通过将字符串括在单引号 (')中形成常量。字符串中的单引号可以通过将两个单引号放在一行中进行编码 - 就像在Pascal中一样。不支持使用反斜杠字符的C样式转义,因为它们不是标准的SQL。

所以O'Brien将在SQL语句输入为O''Brien

和每个这个页面,你可以使用参数化查询:(?,?,?)http://www.sqlite.org/limits.html

INSERT INTO tab1的价值;

然后使用sqlite3_bind_XXXX()函数将大字符串 值绑定到SQL语句。绑定的使用避免了需要在字符串中加入引号字符,从而降低了注入攻击的风险。由于大字符串 不需要被解析或复制,所以它的运行速度也更快。

+0

已经确认两个单引号可以在android SQLite引擎上工作吗?我可以用它作为可行的解决方案。 –

+0

我试了两个单引号......它没有工作。 – worked

0

的一行代码简单:

String s = editText.getText().toString().replace("'","\'"); 
0

只需使用Android标准API为

userInput = android.database.DatabaseUtils.sqlEscapeString(userInput); 

这将解决您的问题。