如果字符串是用C#内插的,如何检查包含字符串的方法内部?

时间:2019-12-25 13:26:22

标签: c# entity-framework parameters arguments interpolation

如果字符串是用C#内插的,怎么可能在接受字符串的方法中进行检查?

我看到EF能够做到这一点here

namespace detail {

template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
    to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
    return { {a[I]...} };
}

}

template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
    return detail::to_array_impl(a, std::make_index_sequence<N>{});
}
  

Entity Framework Core仅在将内插字符串内联提供给FromSql方法调用时才对它们进行参数化。在FromSql方法调用外部声明的插值字符串将不会解析为参数占位符。实际上,您将直接将连接字符串传递给数据库,这是SQL注入的风险。

     

以下示例很危险,不应使用:

// String interpolation
var author = db.Authors.FromSql($"SELECT * From Authors Where AuthorId = {id}").FirstOrDefault();

在阅读上面的摘录之前,我认为在一个方法内部我正在得到一个字符串,并且不可能知道它是如何构造的。摘录使我相信这是有可能的。

1 个答案:

答案 0 :(得分:5)

插值字符串文字可以具有stringFormattableString类型,这取决于类型推断。

EF使用FormattableString作为FromSql的参数类型,因此它既可以使用Format属性获得格式,又可以使用GetArgumentsGetArgument种方法。

这里有一些代码演示了此类的基本用法。

var arg1 = 10;
var arg2 = 20;
FormattableString fs = $"Arg1 is {arg1} and Arg2 is {arg2}.";
Console.WriteLine(fs.Format);
Console.WriteLine(fs.GetArgument(0));
Console.WriteLine(fs.GetArgument(1));

// output:
Arg1 is {0} and Arg2 is {1}.
10
20

因此,FormttableString本质上允许EF阻止SQL注入,因为它“不立即格式化字符串”,而是将格式化字符串包装到一个不错的小对象中,以便EF进行操作。