方法 1:视图中的 HTML 编码<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

阻止 JavaScript 注入***的一种简单方法是重新在视图中显示数据时,用 HTML 编码任何网站用户输入的数据。程序清单 3 中更新的 Index 视图就使用了这种方法。

程序清单 3 Index.aspxHTML 编码后)

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="CustomerFeedback.Views.Home.Index"%>

 

<%@ Import Namespace="CustomerFeedback.Models" %>

 

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

     <h1>Customer Feedback</h1>

     <p>

          Please use the following form to enter feedback about our product.

     </p>

 

     <form method="post" action="/Home/Create">

          <label for="message">Message:</label>

          <br />

          <textarea name="message" cols="50" rows="2"></textarea>

          <br /><br />

          <input type="submit" value="Submit Feedback" />

     </form>

 

     <% foreach (Feedback feedback in ViewData.Model)

     {%>

          <p>

          <%=feedback.EntryDate.ToShortTimeString()%>

          --

          <%=Html.Encode(feedback.Message)%>

          </p>

     <% }%>

 

</asp:Content>

请注意,feedback.Message 的值在显示前使用以下代码进行 HTML 编码:

<%=Html.Encode(feedback.Message)%>

使用 HTML 编码一个字符串的含意是什么呢?使用 HTML 编码字符串时,危险字符如 < > 被替换为 HTML 实体,如 &lt; &gt;。所以,当使用 HTML 编码字符串 <script>alert("Boo!")</script> 时,它将转换为 &lt;script&gt;alert("Boo!")&lt;/script&gt;。浏览器在解析编码的字符串时不再执行 JavaScript 脚本。而是显示无害的页面,如图 3 所示。

3:失败的 JavaScript ***
请注意,程序清单 3 中的 Index 视图只是 feedback.Message 被编码后的值。feedback.EntryDate 的值没有被编码。只需编码用户输入的数据。因为 EntryDate 的值是控制器生成的,所以不需要使用 HTML 编码此值。

方法 2:控制器中的 HTML 编码

除了在视图中显示数据时使用 HTML 编码数据,还可以在将数据提交到数据库之前使用 HTML 编码数据。第二种方法正是程序清单 4 controller 的情况。

程序清单 4 HomeController.csHTML 编码后)

using System;

using System.Web.Mvc;

using CustomerFeedback.Models;

namespace CustomerFeedback.Controllers

{

     [HandleError]

     public class HomeController : Controller

     {

          private FeedbackDataContext db = new FeedbackDataContext();

 

          public ActionResult Index()

          {

               return View(db.Feedbacks);

          }

 

          public ActionResult Create(string message)

          {

               // Add feedback

               var newFeedback = new Feedback();

               newFeedback.Message = Server.HtmlEncode(message);

               newFeedback.EntryDate = DateTime.Now;

               db.Feedbacks.InsertOnSubmit(newFeedback);

               db.SubmitChanges();

 

               // Redirect

               return RedirectToAction("Index");

          }

     }

}

请注意,Message 的值在提交到数据库之前是在 Create() 操作中经过 HTML 编码的。当在视图中重新显示 Message 时,Message HTML 编码,因而不会执行任何注入到 Message 中的 JavaScript

通常,人们喜欢使用本教程中讨论的第一种方法,而不喜欢使用第二种方法。第二种方法的问题在于在数据库中最终会保留 HTML 编码的数据。换言之,数据库中的数据会包含奇怪的字符。

这有什么坏处呢?如果需要用除网页以外的形式显示数据库数据,则将遇到问题。例如,不能轻易在 Windows Forms 应用程序中显示数据