อนุญาตให้ผู้ใช้ป้อน HTML ใน ASP.NET MVC - ValidateInput หรือ AllowHtml


120

ฉันจะอนุญาตให้ผู้ใช้ป้อน HTML ลงในช่องใดช่องหนึ่งโดยใช้ ASP.net MVC ได้อย่างไร

ฉันมีรูปแบบยาวที่มีหลายช่องที่แมปกับวัตถุที่ซับซ้อนนี้ในคอนโทรลเลอร์

ฉันต้องการสร้างหนึ่งฟิลด์ (คำอธิบาย) อนุญาต HTML ซึ่งฉันจะเตรียมการสุขาภิบาลของตัวเองในภายหลัง


3
สำหรับผู้เยี่ยมชมในอนาคต: คำตอบของ IMHO, Chris J หรือ Eugene Bosikov นั้นดีกว่าคำตอบที่ยอมรับสำหรับ ASP.NET MVC รุ่นที่ใหม่กว่าโดยเฉพาะอย่างยิ่งหากคุณต้องการอนุญาต HTML ในช่องเดียวเท่านั้น
lc.

คำตอบ:


163

เพิ่มแอ็ตทริบิวต์ต่อไปนี้การดำเนินการ (โพสต์) ในคอนโทรลเลอร์ที่คุณต้องการอนุญาต HTML สำหรับ:

[ValidateInput(false)] 

แก้ไข:ตามความคิดเห็นของCharlino :

ใน web.config ของคุณตั้งค่าโหมดการตรวจสอบที่ใช้ ดูMSDN :

<httpRuntime requestValidationMode="2.0" />

แก้ไขกันยายน 2014:ตามความคิดเห็นของsprinter252 :

ตอนนี้คุณควรใช้[AllowHtml]แอตทริบิวต์ ดูด้านล่างจากMSDN :

สำหรับแอปพลิเคชัน ASP.NET MVC 3 เมื่อคุณต้องการโพสต์ HTML กลับไปที่โมเดลของคุณอย่าใช้ ValidateInput (เท็จ) เพื่อปิดการตรวจสอบคำขอ เพียงเพิ่ม [AllowHtml] ในคุณสมบัติโมเดลของคุณดังนี้:

public class BlogEntry {
    public int UserId {get;set;}
    [AllowHtml] 
    public string BlogText {get;set;}
 }

1
หากคุณใช้. NET 4 คุณจะต้องตั้งค่า<httpRuntime requestValidationMode="2.0" />ในไฟล์ web.config ของคุณด้วย
Charlino

3
ไม่มีวิธีแก้ปัญหาสำหรับ. NET 4 ที่ไม่รวมการดาวน์เกรดโหมดการตรวจสอบคำขอหรือไม่
bzlm

20
MSDN ( msdn.microsoft.com/de-de/magazine/hh708755.aspx ) กล่าวว่าคุณไม่ควรใช้ ValidateInpute และใช้ AllowHtmlAttribute แทน (ไม่พบเวอร์ชันภาษาอังกฤษ)
Alexander Schmidt

8
ทำการแก้ไขเพื่อหวังว่าจะตอบสนองการโหวต 3 ดาวน์ที่เพิ่งทำไป ... มันเป็นคำตอบ 4 ปี :)
Kelsey

1
@ djack109 โดยทั่วไปคุณไม่ได้ใช้โมเดล EF ของคุณเป็นโมเดลมุมมองของคุณ คุณจะต้องเขียนคลาสแยกต่างหากที่แสดงถึงข้อมูลจริงสำหรับการดำเนินการ CRUD ของคุณ วิธีนี้เมื่อสร้างโมเดล EF6 ขึ้นมาใหม่ไม่มีอะไรสูญหาย นอกจากนี้คุณควรลดขนาดโมเดลลงเพื่อให้มีคุณสมบัติที่จำเป็นเท่านั้นในการทำงานในมือ
Allen Clark Copeland Jr

131

สิ่งที่เกี่ยวกับ[AllowHtml]คุณสมบัติเหนือคุณสมบัติ?


5
นี่เป็นวิธีที่ดีกว่าสำหรับฉันมากโดยหลีกเลี่ยงการเปลี่ยนพฤติกรรมทั่วโลก ฉันเพิ่งแก้ปัญหาของฉันโดยเพิ่มแอตทริบิวต์นี้ในคุณสมบัติในโมเดลของฉัน
Jonathan Sayce

2
เห็นด้วยกับโซลูชันของ Chris ที่นี่ไม่มีเหตุผลที่จะปิดใช้งานการตรวจสอบความถูกต้อง html สำหรับแอปพลิเคชันทั้งหมดหากคุณต้องการเพียงคุณสมบัติเดียวในแบบจำลองเพื่อให้สามารถรับอินพุต html การลบการตรวจสอบความถูกต้องใน web.config จะเปิดช่องโหว่ด้านความปลอดภัยขนาดใหญ่ในแอปของคุณ
มิเกล

1
น่าเสียดายที่สิ่งนี้ใช้ไม่ได้หากคุณใช้MetadataTypeAttribute
dav_i

@dav_i: โซลูชันนี้ทำงานได้ดีMetadataTypeAttributeและเป็นที่ต้องการเนื่องจากอนุญาตให้ใช้ HTML ในแต่ละช่องเท่านั้นแทนที่จะเป็นออบเจ็กต์ทั้งหมด
Gone Coding

@TrueBlueAussie ฉันพยายามมาหลายชั่วโมงแล้วในสภาพแวดล้อม mvc 4.0 ของฉันและแม้ว่า AllowHtml จะใช้งานได้ แต่ก็ไม่ได้ ฉันต้องยอมรับความพ่ายแพ้และเลือกตัวเลือกที่ปลอดภัยน้อยกว่านั่นคือกางเกง AllowHtml ดูเหมือนจะไม่ทำงานกับการใช้ MetadataTypeAttribute
julian guppy

42

เพิ่มในรุ่น:

using System.Web.Mvc;

และต่อทรัพย์สินของคุณ

        [AllowHtml]
        [Display(Name = "Body")]
        public String Body { get; set; }

รหัสนี้จากจุดของฉันวิธีที่ดีที่สุดในการหลีกเลี่ยงข้อผิดพลาดนี้ หากคุณใช้โปรแกรมแก้ไข HTML คุณจะไม่มีปัญหาด้านความปลอดภัยเนื่องจากถูก จำกัด ไว้แล้ว


9

การเพิ่ม[AllowHtml]คุณสมบัติเฉพาะเป็นวิธีที่แนะนำเนื่องจากมีบล็อกและความคิดเห็นมากมายที่แนะนำให้ลดระดับความปลอดภัยซึ่งเป็นสิ่งที่ยอมรับไม่ได้

โดยการเพิ่มนั้นเฟรมเวิร์ก MVC จะช่วยให้คอนโทรลเลอร์ถูกตีและโค้ดในคอนโทรลเลอร์นั้นจะถูกเรียกใช้

อย่างไรก็ตามขึ้นอยู่กับโค้ดตัวกรองและอื่น ๆ ของคุณว่าจะสร้างการตอบกลับอย่างไรและมีการตรวจสอบความถูกต้องเพิ่มเติมที่อาจทำให้เกิดข้อผิดพลาดอื่นที่คล้ายคลึงกันหรือไม่

ไม่ว่าในกรณีใดการเพิ่ม[AllowHtml]แอตทริบิวต์เป็นคำตอบที่ถูกต้องเนื่องจากช่วยให้ html สามารถ deserialized ในคอนโทรลเลอร์ได้ ตัวอย่างใน viewmodel ของคุณ:

[AllowHtml]
public string MessageWithHtml {get; set;}

8

ฉันประสบปัญหาเดียวกันแม้ว่าฉันจะเพิ่ม[System.Web.Mvc.AllowHtml]คุณสมบัติที่เกี่ยวข้องตามที่อธิบายไว้ในบางคำตอบ

ในกรณีของฉันฉันมีUnhandledExceptionFilterคลาสที่เข้าถึงอ็อบเจ็กต์ Request ก่อนที่จะมีการตรวจสอบ MVC (ดังนั้น AllowHtml จึงไม่มีผล) และการเข้าถึงนี้ทำให้เกิดไฟล์[HttpRequestValidationException] A potentially dangerous Request.Form value was detected from the client.

ซึ่งหมายความว่าการเข้าถึงคุณสมบัติบางอย่างของอ็อบเจ็กต์คำขอจะเริ่มการตรวจสอบความถูกต้องโดยปริยาย (ในกรณีของฉันคือParamsคุณสมบัติ)

วิธีการป้องกันการตรวจสอบถูกบันทึกไว้ในMSDN

หากต้องการปิดใช้งานการตรวจสอบคำขอสำหรับฟิลด์เฉพาะในคำขอ (ตัวอย่างเช่นสำหรับองค์ประกอบอินพุตหรือค่าสตริงการสืบค้น) ให้เรียกใช้วิธีการที่ไม่ได้รับการตรวจสอบเมื่อคุณได้รับไอเท็มดังที่แสดงในตัวอย่างต่อไปนี้

ดังนั้นหากคุณมีรหัสเช่นนี้

var lParams = aRequestContext.HttpContext.Request.Params;
if (lParams.Count > 0)
{
  ...

เปลี่ยนเป็น

var lUnvalidatedRequest = aRequestContext.HttpContext.Request.Unvalidated;

var lForm = lUnvalidatedRequest.Form;
if (lForm.Count > 0)
{
  ...

หรือเพียงแค่ใช้Formคุณสมบัติที่ดูเหมือนจะไม่มีการตรวจสอบความถูกต้อง

var lForm = aRequestContext.HttpContext.Request.Form;
if (lForm.Count > 0)
{
  ...

1
ขอบคุณ! คำขอการไม่ผ่านการตรวจสอบเป็นวิธีเดียวที่ใช้ได้ผลสำหรับฉัน
Petter Ivarsson

3

หากคุณต้องการอนุญาตการป้อนข้อมูล html สำหรับพารามิเตอร์ action-method (ตรงข้ามกับ "model property") ไม่มีวิธีในตัวในการทำเช่นนั้น แต่คุณสามารถทำได้อย่างง่ายดายโดยใช้ตัวประสานแบบจำลองที่กำหนดเอง:

public ActionResult AddBlogPost(int userId,
    [ModelBinder(typeof(AllowHtmlBinder))] string htmlBody)
{
    //...
}

รหัส AllowHtmlBinder:

public class AllowHtmlBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;
        var name = bindingContext.ModelName;
        return request.Unvalidated[name]; //magic happens here
    }
}

ค้นหาซอร์สโค้ดที่สมบูรณ์และคำอธิบายในบล็อกโพสต์ของฉัน: https://www.jitbit.com/alexblog/273-aspnet-mvc-allowing-html-for-particular-action-parameters/


1
ดูเหมือนว่า Unvalidated จะใช้ได้เฉพาะในกรอบงาน 4.5 ขึ้นไป
เบ็น

@ เบ็นถูกต้อง! โปรดตรวจสอบโซลูชันที่แก้ไขนี้ stackoverflow.com/questions/59483284/…
om-ha

3

การเข้ารหัส URL ข้อมูลก็ใช้ได้เช่นกันสำหรับฉัน

ตัวอย่างเช่น

var data = '<b> สวัสดี </b>'

ในการเข้ารหัสการโทรของเบราว์เซอร์ UIComponent (ข้อมูล) ก่อนโพสต์

บนเซิร์ฟเวอร์เรียก HttpUtility.UrlDecode (received_data) เพื่อถอดรหัส

ด้วยวิธีนี้คุณสามารถควบคุมพื้นที่เขตข้อมูลที่อนุญาตให้มี html


วิธีที่ง่ายที่สุดจนถึงตอนนี้
N1gthm4r3

1

ฉันประสบปัญหานี้ในระหว่างการพัฒนาไซต์อีคอมเมิร์ซโดยใช้ NopCommerce ฉันได้วิธีแก้ปัญหานี้ด้วยวิธีต่างๆ 3 วิธีเช่นเดียวกับคำตอบก่อนหน้านี้ แต่ตามโครงสร้างของ NopCommerce ฉันไม่พบทั้งสามอย่างในเวลาเดียวกัน ฉันเพิ่งเห็นว่ามีพวกเขาใช้เพียง[AllowHtml]และใช้งานได้ดียกเว้นปัญหาใด ๆ ตามที่เคยถามคำถาม

โดยส่วนตัวแล้วฉันไม่ชอบ[ValidateInput(false)]เพราะฉันกำลังข้ามการตรวจสอบเอนทิตีแบบจำลองทั้งหมดซึ่งไม่ปลอดภัย แต่ถ้าใครเพิ่งเขียนลองดูที่นี่

[AllowHtml] 
public string BlogText {get;set;}

จากนั้นก็ข้ามคุณสมบัติเดียวและอนุญาตเฉพาะคุณสมบัติเฉพาะและตรวจสอบเอนทิตีอื่น ๆ แทบจะไม่ทั้งหมด ดังนั้นจึงเป็นที่นิยมสำหรับฉัน


1

ในกรณีของฉันแอตทริบิวต์ AllowHtml ไม่ทำงานเมื่อรวมกับตัวกรองการดำเนินการ OutputCache คำตอบนี้ช่วยแก้ปัญหาให้ฉันได้ หวังว่านี่จะช่วยใครบางคนได้


1

คุณสามารถใช้[AllowHtml]กับโครงการของคุณได้เช่น

 [AllowHtml]
 public string Description { get; set; }

สำหรับการใช้รหัสนี้กับไลบรารีคลาสคุณติดตั้งแพ็คเกจนี้

Install-Package Microsoft.AspNet.Mvc

หลังการใช้งาน using

using System.Web.Mvc;

0

ไม่มีคำตอบใดที่เหมาะกับฉัน

ฉันลงเอยด้วยการใช้ Custom Model Binding และใช้ Sanitizer ของ บริษัท อื่น

ดูคำถามตัวเองตอบของฉันที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.