java - 在 MySQL SELECT 查询中无法正确识别从 Android POST 请求传递到服务器中 PHP 的字符串

标签 java php android mysql mysqli

我已经对此进行了一段时间的黑客攻击,但我找不到以下行为的充分理由:

我有一个 Android 应用程序,我从中发送一个 multipart/form-data http 帖子。该请求具有以下形式:

    private final String delimiter = "--";
    private final String boundary = "SwA"
                    + Long.toString(System.currentTimeMillis()) + "SwA";
    private final String charset = "UTF-8";
    private final String lineSpace = "\r\n";
    private final String domain = (domain);

    private HttpURLConnection configureConnectionForMultipart(String url)
                    throws MalformedURLException, IOException {
            HttpURLConnection con = (HttpURLConnection) (new URL(url))
                            .openConnection();
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Content-Type", "multipart/form-data;boundary="
                            + boundary);
            return con;
    }

    private void addFormPart(String paramName, String value, DataOutputStream os)
                    throws IOException {
            os.writeBytes(lineSpace + delimiter + boundary + lineSpace);
            os.writeBytes("Content-Disposition: form-data; name=\"" + paramName
                            + "\"" + lineSpace);
            os.writeBytes("Content-Type: text/plain; charset=" + charset + lineSpace);
            os.writeBytes(lineSpace + value + lineSpace);
            os.flush();
    }

    private void addFilePart(String paramName, File data, DataOutputStream os)
                    throws IOException {
            os.writeBytes(lineSpace + delimiter + boundary + lineSpace);
            os.writeBytes("Content-Disposition: form-data; name=\"" + paramName
                            + "\"" + lineSpace);
            os.writeBytes("Content-Type: application/octet-stream\r\n");
            os.writeBytes("Content-Transfer-Encoding: binary" + lineSpace);
            os.writeBytes(lineSpace);
            os.flush();

            FileInputStream fis = new FileInputStream(data);
            byte[] buffer = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
            }
            os.writeBytes(lineSpace);
            os.flush();
            fis.close();
    }

    private void finishMultipart(DataOutputStream os) throws IOException {
            os.writeBytes(lineSpace);
            os.flush();
            os.writeBytes(delimiter + boundary + delimiter + lineSpace);
            os.close();
    }

    private String getResponse(HttpURLConnection con) throws IOException {
            String response = "";
            int status = con.getResponseCode();

            if (status == HttpURLConnection.HTTP_OK) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(
                                    con.getInputStream()));
                    String line = "";
                    while ((line = reader.readLine()) != null) {
                            response += line;
                    }
                    reader.close();
            } else {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(con.getErrorStream()));
                    String line = "";
                    while ((line = reader.readLine()) != null) {
                            response += line;
                    }
                    reader.close();
                    throw new IOException("Server returned non-OK status: " + status+", "+response);
            }
            return response;
    }


public SearchQueryRunnable initSearchQueryRunnable(String query) {
                return new SearchQueryRunnable(query);
        }


    private class SearchQueryRunnable implements Runnable {

            private final String _query;
            private final String _url = domain + "search_query.php";

            public SearchQueryRunnable(String query) {
                    _query = query;
            }

            @Override
            public void run() {
                    try {
                            HttpURLConnection con = configureConnectionForMultipart(_url);
                            DataOutputStream os = new DataOutputStream(
                                            con.getOutputStream());
                            addFormPart("tag", _query, os);
                            finishMultipart(os);
                            String result = getResponse(con);
                            Log.i("SearchQuery", result);
                            con.disconnect();
                    } catch (MalformedURLException e) {
                            e.printStackTrace();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            }
    }

在 search_query.php 中,我有以下内容:

include 'hashtags_table_api.php';

$tag = $_POST["tag"];
$res = queryHashTagsTable($tag);

在hashtags_table_api.php中,有:

include 'connect.php';

function queryHashTagsTable($hashtag) {
    global $pdo;
    $sql = "SELECT * FROM `tbl_hashtags` WHERE hashtag = :hashtag";
    $stmt = $pdo->prepare ( $sql );
    echo $hashtag;
    $stmt->bindValue(':hashtag', $hashtag);
    if ($stmt->execute()) {
        $result = $stmt->fetchAll();
        echo count($result);
    }
}

connect.php 是(省略重要变量):

try {
    $pdo = new PDO ( "mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password );
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo 'Connected to database';
} catch(PDOException $e) {
    echo $e->getMessage();
}

当我运行此代码并将值“hash”传递给 initSearchQueryRunnable 时,我得到的结果为 0,即使我在列主题标签中有一行包含值“hash”。奇怪的是,当我在 search_query.php 中硬编码以下内容时:

include 'hashtags_table_api.php';

$tag = 'hash';
$res = queryHashTagsTable($tag);

我从查询中得到了所需的结果 1。我仔细检查了一下,$_POST["tag"] 正在将值“hash”传递到我的服务器,但由于某种原因,我的 SQL 查询不会将其识别为等于我数据库中的值,即使完全相同的硬编码值被认为是相等的。

知道我还需要做什么才能将动态传递的参数识别为与 MySQL 数据相等的值吗?

编辑

经过一些测试,我意识到 $_POST["tag"] 带有引号,因此 strlen[$tag] = 6。我认为这可能是 SQL 与查询不匹配的原因与数据库中的内容串起来。果然 strlen['hash'] = 4,SQL 成功与我的查询匹配。如何有效地从 $tag 的值中删除引号,以便我的查询有效?仅供引用,我的服务器正在运行 PHP 5.4.24(如果相关的话)。

最佳答案

我在这里解决了我自己的问题。事实证明,通过我的 http 帖子发送的文本有两个额外的不可见空格,我只能通过使用 strlen 的一些测试来检测它们,并使用 for 语句来查看空格附加的位置。我的解决方案是使用 trim() 函数( http://php.net/manual/en/function.trim.php ),并在运行 queryHashTagsTable($tag) 之前简单地将 $tag = trim($tag) 添加到 search_query.php 中。我希望这可以帮助其他人,他们没有意识到他们的 http post 请求是用额外的不可见字符发送的,并且需要 SQL 查询的确切字符串。

关于java - 在 MySQL SELECT 查询中无法正确识别从 Android POST 请求传递到服务器中 PHP 的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26572622/

相关文章:

Java/Swing如何处理不同的屏幕DPI和密度设置?

java - 从 SonarLint 中排除包根?

php - 验证码与否?

php - header 位置延迟

Android requestFocus() 跳过 edittext

java - 通过java中的正则表达式从emailId中找出域

PHP:如何按名称创建类?

android - 如何在不调用 bringToFront() 的情况下将 View 置于最前面?

android - 如何在不恢复中间 fragment 的情况下清除 Android fragment 返回堆栈

java - Mojo.getLog() 方法有什么作用?