首页 > 解决方案 > 无法使用 FormattableString

问题描述

阅读这篇关于 EF Core 中 SQL 注入预防的有趣文章,我发现现在插值字符串可能会导致FormattableString.

在 .NET Core 2.2 中运行此测试代码:

public static void Main()
{
    var filter = "Mark'; DROP TABLE tbl; --";

    Console.WriteLine(FromSql("SELECT * FROM tbl WHERE fld = '" + filter + "'"));
    Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
    Console.WriteLine(FromSql(FormattableStringFactory.Create(
                                  "SELECT * FROM tbl WHERE fld = {0}", filter)));
}

private static string FromSql(string sql) => sql;

private static string FromSql(FormattableString sql)
{   
    var formatArgs = sql.GetArguments();

    for (var paramIndex = 0; paramIndex < sql.ArgumentCount; ++paramIndex)
        formatArgs[paramIndex] = "@p" + paramIndex;

    return sql.ToString();
}

没有达到我的预期:

SELECT * FROM tbl WHERE fld = 'Mark'; DROP TABLE tbl; --'
SELECT * FROM tbl WHERE fld = Mark'; DROP TABLE tbl; --
SELECT * FROM tbl WHERE fld = @p0

第二个打印应该像最后一个一样输出。

试试这是小提琴

我错过了什么?

标签: .net-coreformattablestring

解决方案


您的第二个电话Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));看起来是要FromSql(string sql)重载而不是FromSql(FormattableString sql).

只需删除该FromSql(string sql)方法(以及对它的第一次调用)
它就会按预期进行;请参阅修改后的Fiddle


编译器似乎翻译 var q = $"SELECT * FROM tbl WHERE fld = {filter}";string.

 String q = $"SELECT * FROM tbl WHERE fld = {filter}";`  

由于string类型的原因,String.Format发生了a。
文档

如果内插字符串的类型为string,则通常将其转换为String.Format方法调用。


而明确指定FormattableString

FormattableString q = $"SELECT * FROM tbl WHERE fld = {filter}";  

aFormattableStringFactory.Create正在使用中。
文档

如果内插字符串的类型为 IFormattable 或FormattableString,编译器会生成对FormattableStringFactory.Create方法的调用。


推荐阅读