2016-07-20 8 views
1

私はデータベースにクライアントへの入力要求を受け取るPHPスクリプトを持っていますが、ほとんどの場合は動作しますが、クライアントが名前に特殊文字を含むと失敗する場合もあります。 PHPMyAdminのに手動でクエリを実行し、それが正常に動作し、私が使用していますPHPのコードはここにある:PHP MySQLクエリが失敗する場合がありますか?

$mysql = new mysqli("***", "****", "****", "****"); 
mysqli_set_charset($mysql,"utf8mb4"); 

if (isset($_POST["name"])) { 
$name = $mysql->real_escape_string($_POST["name"]); 
} else { 
mysqli_close($mysql); 
die("Name not set"); 
} 

$query = sprintf ("INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('%s', '%s', '%s', '%s')", $name, $clientip, $steamid, $serverip.":".$serverport); 

if(!$mysql->query($query)) { 
    mysqli_close($mysql); 
    die("Query Failure: " . $query); 
} 

述べたように、上記のコードは、時間の90%に動作しますが、それいくつかのケース(私は特殊文字によって引き起こされると考えています名前で)それは失敗します。ここで

障害が発生した場合は、次のとおりです。

INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('Shrimp%20ᴳᵀ%20ƒ„%20s%20%20t', '****', 'STEAM_1:0:16045698', '178.32.48.195:27015') 
INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('★★%20—%20noichia%20—%20…★', '****', 'STEAM_1:0:103227484', '178.32.48.195:27015') 
INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES ('•%20rie%20Low%20¼rke%20¢%20Ù„', '*****', 'STEAM_1:1:60346821', '178.32.48.195:27015') 

すべてのポスト入力が(唯一の私のサーバーは投稿することができますので、誰かがとにかく悪いことを投稿することができないということ)以下で消毒されています

$mysql->real_escape_string 

私が間違っていることはありますか?

ご協力いただきありがとうございます。

編集:私もURLエンコード私は、以下のものを使用してPHPに要求を送信する前に:

stock void URLEncode(char[] str, int len) 
{ 
char[] str2 = new char[len * 3 + 1]; 
Format(str2, len * 3 + 1, "%s", str); 

char ReplaceThis[20][] = { "%", " ", "!", "*", "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "#", "[", "]" }; 
char ReplaceWith[20][] = { "%25", "%20", "%21", "%2A", "%27", "%28", "%29", "%3B", "%3A", "%40", "%26", "%3D", "%2B", "%24", "%2C", "%2F", "%3F", "%23", "%5B", "%5D" }; 

for (int x = 0; x < 20; x++) { 
    ReplaceString(str2, len, ReplaceThis[x], ReplaceWith[x]); 
} 

if (strlen(str2) > len * 3) { 
    LogError("statistics encode url exceeded length (%d): %s", len * 3, str2); 
} 

Format(str, len, "%s", str2); 

if (strlen(str) > len - 1) { 
    LogError("statistics encode url exceeded length (%d): %s", len, str); 
} 
} 
+4

php文字列関数はユニコード対応ではなく、ユニコードデータをマングルすることができます。手動で作成されたクエリ文字列を使用するべきではありません。プレースホルダでmysqli prepared statementを使用してください。 'sprintf()'はこれを助けません。 - それはまだPHPの文字列関数です。 –

+0

プリペアドステートメントは、これまで私が使ったことがないので避けようとしていたもので、変換するコードがたくさんあります!私は病気が弾丸を噛んだと思う:P – SM9

+0

それは行く唯一の方法です。特に手動でエスケープしてもすべてのSQLインジェクション攻撃が阻止されるわけではないためです。 –

答えて

1

他の人がコメントで指摘したように、あなたがプリペアドステートメントを使用している場合、これははるかに簡単です。 1つのビューにつき複数のレコードを挿入する必要がある場合は、それも速くなります。

コードを変更する方法は次のとおりです。

$mysql = new mysqli("***", "****", "****", "****"); 
mysqli_set_charset($mysql,"utf8mb4"); 

if (isset($_POST["name"])) { 

    $query = $mysql->prepare("INSERT INTO `que` (`name`, `ip`, `steamid`, `serverip`) VALUES (?, ?, ?, ?)") 
    $query->bind_param("ssss", $name, $clientip, $steamid, $serverip.":".$serverport); 

    if($query->execute()) { 
     print 'ok'; 
    } 

} else { 

    print 'Sorry required data not found'; 
} 

明示的に接続を閉じる必要はありません。

+0

私はこれに似た何かを使ってしまいましたが、私はまだいくつかの奇妙なケースで問題を抱えています。 – SM9

+0

素晴らしい。答えを正しいものとしてマークして他の誰かを助けることができればと感謝します。あるいは、このコメントを自分の答えとして投稿し、あなた自身の答えを正しいものとして受け入れてください。その場合は、私のためにupvoteように親切にしてください:) – e4c5

+0

http://paste.ee/p/QBFth#T4TpyLByw7TwSWUWXHwifnHflidf9Q7Rちょうどメモも同様に、あなたはあなたの後ろにifステートメントがあります:P – SM9

関連する問題