在php里实现简单而安全的SQL参数转义
2020-02-11 23:15:22 Author: forum.90sec.com(查看原文) 阅读量:147 收藏

我有一天想到一个问题,json和sql的转义字符这么像(其实很多数据格式的特殊字符都很像),能不能共用一下,我现在认为是可以的。

最初我实现了这样一段代码:

<?php
$username = isset($_GET['username']) ? sqlEscape($_GET['username']) : '""';
$password = isset($_GET['password']) ? sqlEscape($_GET['password']) : '""';

$sql = "SELECT * FROM user where username = {$username} AND password = {$password}";

print $sql;

function sqlEscape($param)
{
	if (is_string($param)) {
		return json_encode($param, JSON_UNESCAPED_UNICODE);
	} else {
		return json_encode(json_encode($param, JSON_UNESCAPED_UNICODE), JSON_UNESCAPED_UNICODE);
	}
}

到这里就差不多了,但是我想了想,前面两段赋值语句,要对每个变量做过滤,有点太啰嗦了,于是改了一下

<?php

$s = new S();

isset($_GET['username'], $_GET['username']) OR exit("username and password is required");

print "SELECT * FROM user WHERE username = {$s->{$_GET['username']}} AND password = {$s->{$_GET['password']}}";

/**
 * SQL转义类
 */
class S
{
	function __get($param)
	{
		if (is_string($param) || is_numeric($param) || is_bool($param) || is_null($param)) {
			return json_encode($param, JSON_UNESCAPED_UNICODE);
		} else {
			return json_encode(json_encode($param, JSON_UNESCAPED_UNICODE), JSON_UNESCAPED_UNICODE);
		}
	}
}

这样一来,实现的就相对优雅一点了

当然,现代化的技术是采用预编译(即参数化查询),原生的参数化查询需要为每一个代码编写冗长的逻辑,于是诞生了一些查询框架,其中最知名的是https://github.com/illuminate/database,内置于laravel,中文社区可能用thinkphp比较多,查询框架见https://github.com/top-think/think-orm

这篇文章的意义主要还是在一些小的思考,可以以一些简单、有效、优雅的方式解决一些小问题(我觉得像那种用双引号、单引号、连字符拼接出来的SQL实在是丑)

此外,任何基于转义的处理方案都不能解决宽字节注入的问题,宽字节问题属于编码不规范导致的,统一后端代码和数据库的编码才能解决:应该统一为utf8(mb4)

完。


文章来源: https://forum.90sec.com/t/topic/747/5
如有侵权请联系:admin#unsafe.sh