0

我有一个要求,我需要在文本中制作可点击的链接,同时将任何其他 html 标签保留为文本(不是 html_safe)。这意味着我无法将整个文本设置为 html_safe,因为这将呈现其他 html 标记,并且我无法清理文本并删除其他 html 标记。我已经看到其他网站通过在自己的行上制作 html_safe 链接和其他文本来处理这个问题。检查 html 时如下所示。

<span>
  "This is an "
  <a href="https://example.com/" target="_blank" rel="nofollow">https://example.com/</a> 
  "other <b>HTML</b>"
</span>

在 Rails 4 中执行此操作的最佳方法是什么?

4

2 回答 2

1

当您调用.html_safe一个字符串时,您实际上会得到一个行为类似于字符串但是ActiveSupport::SafeBuffer. 当您将字符串附加到 a 时,ActiveSupport::SafeBuffer它会自动转义。假设您要构建一个文本是用户输入的跨度:

'<span>'.html_safe + text +'</span>'.html_safe

在这种情况下,我们可以安全地抵御 XXS 攻击,因为来自用户的文本会自动转义:

irb(main):004:0> "<span>".html_safe + "<script>alert('You have been haxxored!')</script>" + "</span>".html_safe
=> "<span>&lt;script&gt;alert(&#39;You have been haxxored&#39;)&lt;/script&gt;</span>"

当视图被构造为ActiveSupport::SafeBuffer. 每当您输出常规字符串时,它将自动转义,因此默认情况下它是安全的。

当然,总会有大量的程序员出于无知而继续给自己一个 XSS 漏洞:

# WAAAH! Rails is escaping my tags! Bad rails!
'<span>'+ text +'</span>'.html_safe

解决该问题的另一种方法是使用标签助手、部分或 Nokogiri,而不是使用字符串连接来构造 HTML,这本身就是乏味的、边界不可读且容易出错的。

于 2020-04-14T20:28:01.477 回答
0

我能够使用以下方法来完成这项工作。

  #module ApplicationHelper
  def url_regexp
    @url_regexp ||= %r{
      (?:(?:https?|ftp|file):\/\/|www\.|ftp\.)
      (?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|
           [-A-Z0-9+&@#\/%=~_|$?!:,.])*
      (?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|
            [A-Z0-9+&@#\/%=~_|$])
    }ix
  end

  #in the view
    <%- "This is a test https://example.com".partition(url_regexp).each do |text| %>
      <%- if text =~ url_regexp %>
        <%= "<a href='#{text}' target='_blank'>#{text}</a>".html_safe %>
      <%- else %>
        <%= text %>
    <% end %>
于 2020-04-16T01:45:04.057 回答