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)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel DB 播种错误禁用 TRIGGER ALL

1 个函数模型 Laravel 中的 2 个序列查询更新

使用 Laravel 在 json 列上创建索引

Laravel 4查询内部视图

Laravel 预防 SQL 注入

Laravel 预防 SQL 注入