Я разрабатываю веб-приложение, используя F #. Думая о защите пользовательских строк ввода от SQL, XSS и других уязвимостей.
В двух словах мне нужны ограничения времени компиляции, которые позволили бы мне отличать простые строки от представлений SQL, URL, XSS, XHTML и т.д.
У многих языков это, например. Свойство строковой интерполяции Rubys #{...}
.
С F # кажется, что Единицы измерения работают очень хорошо, но они доступны только для числовых типов.
Существует несколько решений, в которых используется runtime UoM (ссылка), но я считаю это накладными расходами для моей цели.
Я просмотрел файл FSharpPowerPack, и кажется вполне возможным придумать что-то похожее для строк:
[<MeasureAnnotatedAbbreviation>] type string<[<Measure>] 'u> = string
// Similarly to Core.LanguagePrimitives.IntrinsicFunctions.retype
[<NoDynamicInvocation>]
let inline retype (x:'T) : 'U = (# "" x : 'U #)
let StringWithMeasure (s: string) : string<'u> = retype s
[<Measure>] type plain
let fromPlain (s: string<plain>) : string =
// of course, this one should be implemented properly
// by invalidating special characters and then assigning a proper UoM
retype s
// Supposedly populated from user input
let userName:string<plain> = StringWithMeasure "John'); DROP TABLE Users; --"
// the following line does not compile
let sql1 = sprintf "SELECT * FROM Users WHERE name='%s';" userName
// the following line compiles fine
let sql2 = sprintf "SELECT * FROM Users WHERE name='%s';" (fromPlain userName)
Примечание: это просто образец; не предлагайте использовать SqlParameter
.: -)
Мои вопросы: есть ли приличная библиотека, которая это делает? Есть ли возможность добавить синтаксический сахар?
Спасибо.
Обновление 1: мне нужны ограничения времени компиляции, спасибо Дэниэлу.
Обновление 2. Я пытаюсь избежать накладных расходов во время выполнения (кортежи, структуры, дискриминационные объединения и т.д.).