如果字符串是用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();
在阅读上面的摘录之前,我认为在一个方法内部我正在得到一个字符串,并且不可能知道它是如何构造的。摘录使我相信这是有可能的。
答案 0 :(得分:5)
插值字符串文字可以具有string
或FormattableString
类型,这取决于类型推断。
EF使用FormattableString
作为FromSql
的参数类型,因此它既可以使用Format
属性获得格式,又可以使用GetArguments
和GetArgument
种方法。
这里有一些代码演示了此类的基本用法。
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进行操作。