Я столкнулся с тем же и обнаружил более безопасное решение, чем использование html_safe
, особенно когда вы вводите динамические строки.
Во-первых, обновленный код:
def good_time(long_message1, long_message2, status = true)
html = "".html_safe
html << "Status is #{status}, "
if status
html << long_message1
else
html << long_message2
end
html
end
<%= good_time(true) %>
Это экранирует long_message
содержимое, если оно небезопасно, но оставляет его без экранирования, если оно безопасно.
Это позволяет "long message for success & such."
правильно отображаться, но также экранирует "malicious message <script>alert('foo')</script>"
.
Объяснение сводится к следующему - 'foo'.html_safe
возвращает ActiveSupport :: SafeBuffer, который действует как строка во всех отношениях, кроме одного: когда вы добавляете строку в SafeBuffer (путем вызова + или <<), этот другой String экранируется в HTML перед добавлением в SafeBuffer. Когда вы добавляете другой SafeBuffer к SafeBuffer, экранирование не происходит. Rails отображает все ваши представления под капотом, используя SafeBuffers, поэтому обновленный метод, приведенный выше, в итоге предоставляет Rails SafeBuffer, который мы контролируем для выполнения экранирования на <code>long_message «по необходимости», а не «всегда».
Теперь, заслуга в этом ответе целиком и полностью принадлежит Хеннингу Коху и более подробно объяснена на Все, что вы знаете о html_safe, неверно - мое резюме выше пытается только дать суть объяснение в случае, если эта ссылка когда-либо умирает.