DB::statement();在 Laravel (5.5)
Posted
技术标签:
【中文标题】DB::statement();在 Laravel (5.5)【英文标题】:DB::statement(); in Laravel (5.5) 【发布时间】:2018-07-15 01:22:43 【问题描述】:我正在使用 Laravel 5.5 构建一个应用程序,我必须为 Eloquent ORM (PostGIS) 不支持的扩展 PostgreSQL 运行一些 SQL 查询。相反,我使用 DB::statement($queryString);将数据插入数据库。 $queryString 由输入变量与预构建的 SQL 语句连接而成。
这是来自我的控制器的代码(注意实际查询更复杂,这只是一个示例):
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
$id= $request->input('id');
$name= $request->input('name');
$geom = $request->input('geom');
$geom = DB::raw("ST_TRANSFORM(ST_GeomFromGeoJSON('".$geom."'), 3857)");
$statement = "INSERT INTO tableName(id, name) VALUES ('".$id."', '".$name."', ".$geom.");";
DB::statement($statement);
return 'Insert Successful';
我对这种方法有两个问题:
如何保护我的应用程序免受 SQL 注入攻击?
如何检查查询是否成功运行? DB::statement 似乎没有返回任何内容。
【问题讨论】:
我想你应该参考手册。 为什么要使用查询插入? Laravel 文档中有一些示例。 laravel.com/docs/5.5/database#running-queries 正是@pankajMakwana 是对的,你为什么要使用查询来插入数据。 Use Eloquent where possible 保证代码安全和可维护。看看我的 repo 中的例子,你还想使用原始查询吗? 【参考方案1】:1,使用参数绑定来保护您的查询。示例:
$users = DB::select('select * from users where active = ?', [1]);
https://laravel.com/docs/5.5/database#running-queries
至于 #2,将您的查询封装在 database transactions 中。这将防止失败。示例:
DB::transaction(function ()
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
);
【讨论】:
谢谢,我一直认为参数绑定对sql注入是安全的。我正在考虑使用准备好的语句,虽然安全是乏味的。因此,如果参数绑定足以提供保护,我将使用它而不是繁琐的准备好的语句。【参考方案2】:你可以在导入后做这个
use Illuminate\Support\Facades\DB;
你可以像这样纠正你的查询
$quert=DB::insert('insert into tablename (columnname1,columnname2,) values (?,?)',[$id,$username]);
如果您想将整个数据插入到表中,但何时表中除了 id 和用户名之外没有数据
$quert=DB::insert('insert into tablename values (?,?)',[$id,$username]);
问号是问号吗? :D 不要在这里输入任何内容 不客气
编辑:
关于 如何保护我的应用程序免受 SQL 注入攻击? 你可以从中间件制作这个,使用像
这样的跨站点脚本% raw % % endraw %
使用 CSRF
<form ...>
!! csrf_field() !!
</form>
第二个问题 你有很多东西
1-简单的方法
您可以返回您的查询 如果您选择它将返回选择 如果它插入/更新/删除,则为真,否则为假
return response()->json([
'Message'=>'what ever you wanna write',
'Data' => $query,
], 200);
2-hard way(我更喜欢:D)
您可以使用 DB::listen 进行调试
DB::listen(function ($query)
// $query->sql
// $query->bindings
// $query->time
);
【讨论】:
【参考方案3】:一般来说,根据OWASP,有四种方法可以防止SQL注入。
-
准备好的声明
存储过程
白名单/输入验证
转义所有用户提供的输入
在您的情况下,对于 Eloquent ORM 不能直接工作的 Laravel 5+,我认为最好的选择是 #1,Prepared Statements。
更具体地说,在 Laravel 中,您可以实现它内置于 Query Builder 以迭代构建语句或使用
执行完全原始的 SQL 语句DB:: select ( [raw query string] )
来源
SO Post: Laravel, execute raw queries
【讨论】:
所以在普通 DB:insert 中使用的参数绑定不能保护 SQL 注入?换句话说,它没有在内部实现准备好的语句?我尝试将 DB::statement 用于准备好的语句,但不起作用。然后我尝试 DB::raw 来执行我准备好的语句,它起作用了。以上是关于DB::statement();在 Laravel (5.5)的主要内容,如果未能解决你的问题,请参考以下文章