EntityFramework Core 2.0执行原始查询如何防止SQL注入?

前言

接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助。

EntityFramework Core执行原始查询

在EntityFramework Core中执行原始查询我们借助FromSql来实现,如下:

            using (var context = new EFCoreDbContext())
            {
                var orders = context.Orders
                    .FromSql("SELECT * FROM dbo.Orders")
                    .ToList();
            }    

这是最简单且不带任何条件的查询方式,接下来我们看看有条件的查询我们应该如何查询,如下:

            using (var context = new EFCoreDbContext())
            {
                var parameters = new SqlParameter[]
                {
                    new SqlParameter(){ ParameterName = "@p0", Value = 1, SqlDbType = System.Data.SqlDbType.Int }
                };

                var orders = context.Orders
                    .FromSql("SELECT * FROM dbo.Orders WHERE Id = @p0", parameters)
                    .ToList();
            }

除了以上利用参数化查询方式外,若我们还借助string.format或者C# 6.0出现的新特性字符串插值即美元符号$来查询最终生成的SQL是否仍然是以参数化查询呢,我们来看看。

            using (var context = new EFCoreDbContext())
            {

                var orders = context.Orders
                    .FromSql($"SELECT * FROM dbo.Orders WHERE Id = {1}")
                    .ToList();
            }

由上我们看出即使利用字符串插值最终仍然翻译成参数化SQL。接下来我们再来看看字符串拼接查询方式。

            using (var context = new EFCoreDbContext())
            {

                var searchString = "Jeffcky";

                var blogs = context.Blogs
                    .FromSql("SELECT Id, Name, CreatedTime, Url, ModifiedTime FROM dbo.Blogs " +
                    "WHERE Name = ‘" + searchString + "‘")
                    .ToList();
            }

此时我们通过控制台打印能够看出最终生成的SQL语句是以字符串形式展示,在EntityFramework Core 2.0+上执行原始查询的APi即FromSql有重载方法,如下:

public static IQueryable<TEntity> FromSql<TEntity>([NotNullAttribute] this IQueryable<TEntity> source, [NotNullAttribute][NotParameterized] FormattableString sql) where TEntity : class;

我们利用上述FromSql重载方法传递字符串参数,同时在查询字符串中添加对数据库表操作,验证EF Core是否能防止SQL注入。

            using (var context = new EFCoreDbContext())
            {

                var searchString = "Jeffcky; DROP TABLE dbo.Blogs;";

                var blogs = context.Blogs
                    .FromSql("SELECT Id, Name, Url, CreatedTime, ModifiedTime FROM dbo.Blogs "
                    + " WHERE Name = {0}", searchString)
                    .ToList();
            }

经过验证您会发现上述我们注入上述Blogs表的SQL语句,最终表将不会删除。我们看到当未利用重载方法进行字符串拼接,此时参数将以字符串形式展示,这种情况极易引起SQL注入问题。C# 6.0引入了字符串插值(String Interpolation),此特性能够允许C#表达式直接嵌入到字符串文本中,为运行时构建字符串提供了一个很好的方法。在EF Core 2.0特性中,对FromSql和ExecuteSqlCommand方法都添加了对插入字符串的特殊支持。此新特性的支持允许以安全的方式使用C#字符串插值。即防止在运行时动态构建SQL时可能发生SQL注入问题。

是不是到了这里就这样结束了呢?显然不是这样,接下来咱们再来看看另外一种情况,如下:

            using (var context = new EFCoreDbContext())
            {

                var author = "Jeffcky Wang";
                var query = $"SELECT * FROM Blogs WHERE Name = {author}";
                var blogs = context.Blogs.FromSql(query).ToList();
            }

这样的语法错误显而易见,我们需要用单引号将变量包含起来才能避免语法错误,如下:

            using (var context = new EFCoreDbContext())
            {

                var author = "Jeffcky Wang";
                var query = $"SELECT * FROM Blogs WHERE Name = ‘{author}‘";
                var blogs = context.Blogs.FromSql(query).ToList();
            }

上述情况下,EF Core依然将执行明文字符串而不是作为变量查询并未以参数化执行。如果变量包含恶意字符串,那么EF Core将根本无法防范并保护SQL。因此,如果我们需要通过EF Core执行原始T-SQL,则应使用参数化SQL或利用FormatttableString,FromSql有两个重载,其一为通过FormatttableString可格式化字符串参数,其二为原始字符串且可传递查询参数。所以上述错误,我们可利用FormatttableString来执行,同时在利用FromSql方法查询过后我们仍可以继续进行查询,比如如下关联查询Posts表数据。

            using (var context = new EFCoreDbContext())
            {

                var searchString = "Jeffcky Wang";

                FormattableString sql = $@"SELECT Id, Name, Url, CreatedTime, ModifiedTime FROM dbo.Blogs WHERE Name = {searchString}";

                var blogs = context.Blogs
                    .FromSql(sql)
                    .Include(d => d.Posts)
                    .ToList();
            }

通过【[email protected]】并利用FormattableString重载或者传递参数化变量来防止SQL注入问题,希望您发现EF Core 2.0中这个新特性,同时不要忘记它也用来承担更大的责任,由于SQL注入攻击,不会让我们所写代码存在漏洞。

总结

本节我们详细讲解了EF Core 2.0中执行原始查询如何防止SQL注入问题,精简的内容,简单的讲解,希望能帮助到您。我们明天再会。

原文地址:https://www.cnblogs.com/CreateMyself/p/8481331.html

时间: 2024-12-09 03:32:46

EntityFramework Core 2.0执行原始查询如何防止SQL注入?的相关文章

EntityFramework Core 2.0自定义标量函数两种方式

前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将方法映射到数据库中的标量函数,我们可在LINQ中调用此方法并会被正确翻译成SQL语句,这为编写数据访问层的开发人员提供了一个很棒的功能来创建一个方法并在其上应用DbFunction特性即可.该属性会将静态CLR方法映射到数据库函数,以便可以在LINQ查询中使用此方法.默认情况下,数据库函数中的CLR

参数化查询为什么能够防止SQL注入

很多人都知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的. 本文主要讲述的是这个问题,也许你在部分文章中看到过这块内容,当然了看看也无妨. 首先:我们要了解SQL收到一个指令后所做的事情: 具体细节可以查看文章:Sql Server 编译.重编译与执行计划重用原理 在这里,我简单的表示为: 收到指令 -> 编译SQL生成执行计划 ->选择执行计划 ->执行执行计划. 具体可能有点不一样,但大致的步骤如上所示. 接着我们来分析为什么拼接SQ

参数化查询为什么能够防止SQL注入 (转)

很多人都知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的. 本文主要讲述的是这个问题,也许你在部分文章中看到过这块内容,当然了看看也无妨. 首先:我们要了解SQL收到一个指令后所做的事情: 具体细节可以查看文章:Sql Server 编译.重编译与执行计划重用原理 在这里,我简单的表示为: 收到指令 -> 编译SQL生成执行计划 ->选择执行计划 ->执行执行计划. 具体可能有点不一样,但大致的步骤如上所示. 接着我们来分析为什么拼接SQ

为什么参数化查询可以防止SQL注入?(转)

昨天被某大牛问了一个问题,为什么SQL参数化查询可以防止SQL注入,参数化查询的原理是什么? 结果闷逼了,之前只知道参数化查询是可以防止SQL注入,但是没有深究其原理,今天就找一些文章,学习一下,也分享给大家. 以下引用知乎大神们的回答: 原理是采用了预编译的方法,先将SQL语句中可被客户端控制的参数集进行编译,生成对应的临时变量集,再使用对应的设置方法,为临时变量集里面的元素进行赋值,赋值函数setString(),会对传入的参数进行强制类型检查和安全检查,所以就避免了SQL注入的产生. 最近

基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(1) - 依赖注入三层框架搭建

概述 本文章描述如何搭建 ASP.NET Core 2.0 WebAPI 依赖注入三层架构,为什么要加入依赖,并不是为了提供程序性能,而是为了项目间解耦,项目之间能够更加独立. 微软爸爸官方说明文档:在 ASP.NET Core 依赖注入 全面理解 ASP.NET Core 依赖注入 步骤 1. 新建解决方案,添加一个ASP.NET Core WebApi应用 2. 添加四个.Net Core类库:Entity.BLL.DAL.Common 3. 按照以下截图进行解决方案布局 4. 添加DAL层

Entity Framework Core 2.0 新特性

本文翻译来自:https://docs.microsoft.com/en-us/ef/core/what-is-new/index 一.模型级查询过滤器(Model-level query filters) ef core2.0包含了一个新特性,我们叫他模型级查询过滤器(Model-level query filters).此特性允许使用Linq查询表达式直接定义在实体类型的元数据模型上.这样的过滤器会自动应用到任何LINQ查询所涉及的那些实体类型,包括间接引用的实体类型(对象引用,导航属性).

django 执行原始SQL

二.知识点总结 When the model query APIs don’t go far enough, you can fall back to writing raw SQL. go far enough:远远不够fall back to:求助 raw:原始的,未加工的 Django提供两种方式执行(performing)原始的SQL查询: (1) . Manager.raw():执行原始查询并返回模型实例 (2) . Executing custom SQL directly :直接执

在django中,执行原始sql语句

extra()方法 结果集修改器,一种提供额外查询参数的机制 使用extra: 1:Book.objects.filter(publisher__name='广东人员出版社').extra(where=['price>50']) Book.objects.filter(publisher__name='广东人员出版社',price__gt=50) 2:Book.objects.extra(select={'count':'select count(*) from hello_Book'}) ra

ASP.NET Core 开发-Entity Framework (EF) Core 1.0 Database First

ASP.NET Core 开发-Entity Framework Core 1.0 Database First,ASP.NET Core 1.0 EF Core操作数据库. Entity Framework Core 1.0 也已经发布了,可以适用于 .NET Core 1.0 及ASP.NET Core 1.0 . EF Core RC2 时,使用的Code First: http://www.cnblogs.com/linezero/p/EntityFrameworkCore.html E