【问题标题】:How do I allow HTML tags to be submitted in a textbox in asp.net?如何允许在 asp.net 的文本框中提交 HTML 标签?
【发布时间】:2012-07-25 06:20:54
【问题描述】:

首先,我想让大家知道我使用的是 aspx 引擎而不是 Razor 引擎。

我在表单中有一个表格。我的一个文本框包含 html 标签,如

</br>Phone: </br> 814-888-9999 </br> Email: </br> aaa@gmail.com.  

当我去构建它时,它给了我一个错误,上面写着:

从客户端 (QuestionAnswer="...ics Phone:&lt;br/&gt;814-888-9999&lt;br...") 检测到有潜在危险的 Request.Form 值。

我尝试了验证 request="false" 但没有成功。

很抱歉,到目前为止,我没有添加我的 html 代码供您查看。如果需要,我正在提出一些可以编辑的问题。

 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"   Inherits="System.Web.Mvc.ViewPage<dynamic>" %>


<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
EditFreqQuestionsUser
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
$(document).ready(function () {
    $("#freqQuestionsUserUpdateButton").click(function () {
        $("#updateFreqQuestionsUser").submit();
    });
});
</script>
<h2>Edit Freq Questions User </h2>

<%Administrator.AdminProductionServices.FreqQuestionsUser freqQuestionsUser =   ViewBag.freqQuestionsUser != null ? ViewBag.freqQuestionsUser : new   Administrator.AdminProductionServices.FreqQuestionsUser(); %>
<%List<string> UserRoleList = Session["UserRoles"] != null ? (List<string>)Session["UserRoles"] : new List<string>(); %>
<form id="updateFreqQuestionsUser" action="<%=Url.Action("SaveFreqQuestionsUser","Prod")%>" method="post" onsubmit+>
<table> 
    <tr>
        <td colspan="3" class="tableHeader">Freq Questions User Details <input type ="hidden" value="<%=freqQuestionsUser.freqQuestionsUserId%>" name="freqQuestionsUserId"/> </td>
    </tr>
     <tr>
        <td colspan="2" class="label">Question Description:</td>
        <td class="content">
            <input type="text" maxlength="2000" name="QuestionDescription" value="  <%=freqQuestionsUser.questionDescription%>" />
        </td>
    </tr>
     <tr>
        <td colspan="2" class="label">QuestionAnswer:</td>
        <td class="content">
            <input type="text" maxlength="2000" name="QuestionAnswer" value="<%=freqQuestionsUser.questionAnswer%>" />
        </td>
    </tr>
    <tr>
        <td colspan="3" class="tableFooter">
                <br />
                <a id="freqQuestionsUserUpdateButton" href="#" class="regularButton">Save</a>
                <a href="javascript:history.back()" class="regularButton">Cancel</a>
        </td> 
    </tr>
    </table>
      </form>
</asp:Content>

【问题讨论】:

    标签: c# javascript asp.net-mvc decoding


    【解决方案1】:

    在提交页面之前,您需要使用 window.escape(...) 对文本框的值进行 html 编码

    如果您需要服务器端未转义的文本,请使用HttpUtility.UrlDecode(...) 方法。

    非常快速的示例:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="SO.WebForm1" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <script>
            function makeSafe() {
                document.getElementById('TextBox1').value = window.escape(document.getElementById('TextBox1').value);
            };
    
            function makeDangerous() {
                document.getElementById('TextBox1').value = window.unescape(document.getElementById('TextBox1').value);
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server" onsubmit="makeSafe();">
        <div>
            <asp:TextBox ID="TextBox1" runat="server" TextMode="MultiLine" Rows="10" ClientIDMode="Static"></asp:TextBox>
        </div>
        <asp:Button ID="Button1" runat="server" Text="Button" />
        </form>
    
    
         <script>
             makeDangerous();
        </script>
    </body>
    </html>
    

    对您的代码进行以下更改:

    <script type="text/javascript">
        $(document).ready(function () {
            makeDangerous();
            $("#freqQuestionsUserUpdateButton").click(function () {
                makeSafe();
                $("#updateFreqQuestionsUser").submit();
            });
        });
    
        // Adding an ID attribute to the inputs you want to validate is simplest
        // Better would be to use document.getElementsByTagName and filter the array on NAME
        // or use a JQUERY select....
    
        function makeSafe() {
            document.getElementById('QuestionAnswer').value = window.escape(document.getElementById('QuestionAnswer').value);
        };
    
        // In this case adding the HTML back to a textbox should be 'safe'
        // You should be very wary though when you use it as actual HTML
        // You MUST take steps to ensure the HTML is safe.
        function makeDangerous() {
            document.getElementById('QuestionAnswer').value = window.unescape(document.getElementById('QuestionAnswer').value);
        }
    </script>
    

    【讨论】:

      【解决方案2】:

      使用[ValidateInput] 属性装饰您的控制器操作:

      [ValidateInput(false)]
      [HttpPost]
      public ActionResult Foo(MyViewModel model)
      {
          ...
      }
      

      【讨论】:

      • -1:虽然这是一个有效的答案,但它不是一个好的答案。我认为建议用户盲目禁用验证并不是一个好主意。相反,他们应该确定为什么验证失败,然后提出一个解决方案,而不仅仅是关闭一个重要的安全机制。 Ted SpenceAdrian 提供的建议是一个很好的起点。
      • @KevinBabcock,重要的安全机制?我对此一笑置之。你能解释一下这个验证有什么重要的吗?此外,您仅针对此特定操作禁用验证。在 ASP.NET MVC 3 中,您可以通过使用 [AllowHtml] 属性装饰视图模型属性来实现更细粒度的逻辑。在提交之前使用 javascript 转义用户输入有什么意义?
      • 认真的吗?你在争论输入验证是可笑的和不重要的?用户输入的“不正确中和”是listed in first 3 of the top 25 security vulnerabilities in software today。你只是告诉那个人禁用输入验证,根本没有任何解释。没有解释,没有选择,什么都没有。
      • 在将用户输入提交到服务器之前使用编码有什么意义?查看XSS prevention rule #2。显然这只是第一道防线,输入也应该在服务器上进行验证。
      • 这是旧的,但@DarinDimitrov 是正确的,我知道如何验证我自己的输入,在这里我特别希望 HTML 允许 - 就像标题说的那样。
      【解决方案3】:

      客户端 JavaScript:

      function codificarTags() 
      {
           document.getElementById('txtDescripcion').value = document.getElementById('txtDescripcion').value.replace(/</g,'&lt;').replace(/>/g,'&gt;');
      }
          
      <form id="form1" runat="server" onsubmit="codificarTags();">
      

      服务器:

      protected void Page_Load(object sender, EventArgs e)
      {
           txtDescripcion.Text = txtDescripcion.Text.Replace(@"&lt;", @"<").Replace(@"&gt;", @">");
      }
      

      【讨论】:

        【解决方案4】:

        我建议使用 AjaxControlToolkit 的 HTML 编辑器。我现在正在实施。如果您的文本框是多行的并且足够大以容纳 HTML,为什么不将其添加到 HTML 编辑器中。您的用户也会更快乐。

        http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/HTMLEditor/HTMLEditor.aspx

        【讨论】:

          【解决方案5】:

          在文本框中使用 html 不是一个好习惯,也许使用换行符 (Environment.NewLine) 或 \r\n 而不是 br.NET Reference

          示例(在 C# 中):

          textBox1.Multiline = true;
          textBox1.Text = "test" + Environment.NewLine + "test2";
          

          【讨论】:

          • 我可以在文本框/ /n 或 /r 中使用它吗?
          • 我把 \n 放在了文本框中,它不起作用。它也没有给我一个错误。它只是输入了\n,所以现在它就像\n814-888-9999
          • @Yusuf 如果文本框的类型是多行的,它就是!使用 text1.text= "test" + "\r\n" + "test2";
          • 对不起,我颠倒了\n和\r,这是\r\n为了工作。更改 freqQuestionsUser.questionAnswer 应该没问题
          【解决方案6】:

          我采取了一些不同的方法。我想在我的应用程序中广泛使用 html 文本框。我制作了一个用户控件,可以避免每次添加新控件时都编辑 javascript。我的整个控件非常自定义,但 html 处理的核心如下所示。

          UserControl 标记有一些简单的 javascript 来转义和取消转义文本框。

          <script type="text/javascript">
          
              function UnescapeControl(clientId) {
                      $('#' + clientId).val(window.unescape($('#' + clientId).val()));
              }
          
              function EscapeAllControls() {
                 var escapeControList = JSON.parse('<%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(EscapeControlList) %>');
                 for (var i = 0; i < escapeControList.length; i++) 
                     EscapeControl(escapeControList[i]);            
              }
          
              function EscapeControl(textClientId) {
                 document.getElementById(textClientId).value = window.escape(document.getElementById(textClientId).value); 
              }
          </script>
          
          <asp:TextBox ID="Txt_SavableText" CssClass="form-control" Width="100%" runat="server" ></asp:TextBox>
          

          后面的代码负责在回发前使用RegisterOnSubmitStatement 转义控件,并在回发后使用RegisterStartupScript 取消转义。

          public partial class SavableTextBox : System.Web.UI.UserControl
          {
          
              public List<string> EscapeControlList
              {
                  get
                  {
                      if (Session["STB_EscapeControlList"] == null)
                          Session["STB_EscapeControlList"] = new List<string>();
                      
                      return (List<string>)Session["STB_EscapeControlList"];
                  }
                  set { Session["STB_EscapeControlList"] = value; }
              }
          
              
          
              protected void Page_Load(object sender, EventArgs e)
              {
                  if (EscapeHtmlOnPostback && !EscapeControlList.Contains(GetClientId()))
                      EscapeControlList.Add(GetClientId());
          
                  // When using a script manager, you should use ScriptManager instead of ClientScript.
                  if (EscapeHtmlOnPostback)
                      ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "UnescapeControl_" + GetClientId(), "UnescapeControl('" + GetClientId() + "');", true);
          
                  // Ensure we have our escape script called before all post backs containing escapable controls.
                  // This is like calling OnClientClick before everything.
                  if (EscapeControlList != null && EscapeControlList.Count > 0)
                      this.Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "SaveableTextBoxEscaper", "EscapeAllControls();");
                  
              }
          
          
             public string Text
              {
                  get
                  {
                      return Txt_SavableText.Text;
                  }
                  set
                  {
                      Txt_SavableText.Text = value;
                  }
              }
          
              public string GetClientId()
              {
                  return Txt_SavableText.ClientID;
              }
          }
          

          现在我们可以像这样在设置EscapeHtmlOnPostback="True"时在任何地方使用它。

          <%@ Register TagPrefix="STB" TagName="SavableTextBox" Src="~/SavableTextBox.ascx" %>
          <STB:SavableTextBox ID="Txt_HtmlTextBox" EscapeHtmlOnPostback="True" runat="server" />
          

          注意,当我们在回发期间访问Txt_HtmlTextBox.Text 时,它已经为我们转义了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-08-20
            • 2011-05-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-01-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多