前言

接下来一段时间我们来讲讲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 = , 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();
}

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

总结

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

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

  1. EF Core 2.0 执行原始查询如何防止SQL注入

    using (var context = new EFCoreDbContext()) { var searchString = "Jeffcky Wang"; Formattab ...

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

    前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将 ...

  3. EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)

    前言 EntityFramework Core 2.0引入了显式编译查询,在查询数据时预先编译好LINQ查询便于在请求数据时能够立即响应.显式编译查询提供了高可用场景,通过使用显式编译的查询可以提高查 ...

  4. EntityFramework Core 2.0全局过滤(HasQueryFilter)

    前言 EntityFramework Core每一次版本的迭代和更新都会带给我们惊喜,每次都会尽量满足大部分使用者的需求.在EF Core 2.0版本中出现了全局过滤新特性即HasQueryFilte ...

  5. .NetCore技术研究-EntityFramework Core 3.0 Preview

    前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...

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

    很多人都知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的. 本文主要讲述的是这个问题,也许你在部分文章中看到过这块内容,当然了看看也无妨. 首先:我们 ...

  7. EntityFramework Core 3.0查询

    前言 随着.NET Core 3.0的发布,EF Core 3.0也随之正式发布,关于这一块最近一段时间也没太多去关注,陆续会去对比之前版本有什么变化没有,本节我们来看下两个查询. 分组 我们知道在E ...

  8. 【挖洞经验】如何在一条UPDATE查询中实现SQL注入

    直奔主题 跟往常一样,在喝完我最爱的果汁饮料之后,我会习惯性地登录我的Synack账号,然后选择一个应用来进行渗透测试,此时我的“黑客之夜”便正式开始了. 我与很多其他的安全研究人员的习惯一样,我会在 ...

  9. 为什么预处理和参数化查询可以防止sql注入呢?

    在传统的写法中,sql查询语句在程序中拼接,防注入(加斜杠)是在php中处理的,然后就发语句发送到mysql中,mysql其实没有太好的办法对传进来的语句判断哪些是正常的,哪些是恶意的,所以直接查询的 ...

随机推荐

  1. Oracle问题之literal does not match format string

    问题: oerr ora 186101861, 00000, "literal does not match format string"// *Cause: Literals i ...

  2. [知了堂学习笔记]_记一次BootStrap的使用

    效果图如下: 一.简介: 什么是Bootstrap?  Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架. 什么是响应式布局? 引用一句Bootstrap的标题语 " ...

  3. List源码学习之ArrayList

    ArrayList 内部结构为一个可重复的对象数组(可存空对象). 内部有以下几个参数: ;/** * 用于空实例的共享空数组实例 */private static final Object[] EM ...

  4. 理解rem实现响应式布局原理及js动态计算rem

    前言 移动端布局中,童鞋们会使用到rem作为css单位进行不同手机屏幕大小上的适配.那么来讲讲rem在其中起的作用和如何动态设置rem的值. 1.什么是rem rem是相对于根元素(html标签)的字 ...

  5. tinyproxy实现https正向代理

    安装 yum install tinyproxy -y 配置 # vim /etc/tinyproxy/tinyproxy.conf ## ## tinyproxy.conf -- tinyproxy ...

  6. python_6_字符串

    什么是字符串? --一般用户输入数据和一堆有意义或者没有意义的文字符号组合 对字符串有哪些操作? --字符串本身不能修改,可以切片,可以读取 -- .capitalize()              ...

  7. 1.JavaScript 教程:基础语法

    简介: JavaScript web 开发人员必须学习的 3 门语言中的一门: HTML 定义了网页的内容 CSS 描述了网页的布局 JavaScript 网页的行为 用法: (1)HTML 中的脚本 ...

  8. CentOS修改Tomcat端口号

    Linux下修改Tomcat默认端口 1.方法一 假设tomcat所在目录为/usr/local/apache-tomcat/ 1.打开tomcat配置文件 # vi /usr/local/apach ...

  9. Android5.0新控件

    谷歌在推出Android5.0的同时推出了一些新控件,Android5.0中最常用的新控件有下面5种.  1. CardView(卡片视图) CardView顾名思义是卡片视图,它继承FrameLay ...

  10. redis数据类型-字符串类型

    Redis数据类型 字符串类型 字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据.你可以用其存储用户的邮箱.JSON化的对象甚至是一张图片.一个字符串类型键允许存储的 ...