转:http://www.oschina.net/code/snippet_222150_9776

与原文代码略有改动

 /// <summary>/// Html 脚本过滤/// </summary>public class NHtmlFilter{protected static readonly RegexOptions REGEX_FLAGS_SI = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled;private static string P_COMMENTS = "<!--(.*?)-->";private static Regex P_COMMENT = new Regex("^!--(.*)--$", REGEX_FLAGS_SI);private static string P_TAGS = "<(.*?)>";private static Regex P_END_TAG = new Regex("^/([a-z0-9]+)", REGEX_FLAGS_SI);private static Regex P_START_TAG = new Regex("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);private static Regex P_QUOTED_ATTRIBUTES = new Regex("([a-z0-9|(a-z0-9\\-a-z0-9)]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);private static Regex P_UNQUOTED_ATTRIBUTES = new Regex("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);private static Regex P_PROTOCOL = new Regex("^([^:]+):", REGEX_FLAGS_SI);private static Regex P_ENTITY = new Regex("&#(\\d+);?");private static Regex P_ENTITY_UNICODE = new Regex("&#x([0-9a-f]+);?");private static Regex P_ENCODE = new Regex("%([0-9a-f]{2});?");private static Regex P_VALID_ENTITIES = new Regex("&([^&;]*)(?=(;|&|$))");private static Regex P_VALID_QUOTES = new Regex("(>|^)([^<]+?)(<|$)", RegexOptions.Singleline | RegexOptions.Compiled);private static string P_END_ARROW = "^>";private static string P_BODY_TO_END = "<([^>]*?)(?=<|$)";private static string P_XML_CONTENT = "(^|>)([^<]*?)(?=>)";private static string P_STRAY_LEFT_ARROW = "<([^>]*?)(?=<|$)";private static string P_STRAY_RIGHT_ARROW = "(^|>)([^<]*?)(?=>)";private static string P_AMP = "&";private static string P_QUOTE = "\"";private static string P_LEFT_ARROW = "<";private static string P_RIGHT_ARROW = ">";private static string P_BOTH_ARROWS = "<>";// @xxx could grow large... maybe use sesat's ReferenceMapprivate static Dictionary<String, string> P_REMOVE_PAIR_BLANKS = new Dictionary<String, string>();private static Dictionary<String, string> P_REMOVE_SELF_BLANKS = new Dictionary<String, string>();/** * flag determining whether to try to make tags when presented with "unbalanced"* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>").  If set to false,* unbalanced angle brackets will be html escaped.*/protected static bool alwaysMakeTags = true;/*** flag determing whether comments are allowed in input String.*/protected static bool stripComment = true;/// <summary>/// 不允许/// </summary>private String[] vDisallowed { get; set; }/// <summary>/// 允许/// </summary>protected Dictionary<String, List<String>> vAllowed { get; set; }/** counts of open tags for each (allowable) html element **/protected Dictionary<String, int> vTagCounts;/** html elements which must always be self-closing (e.g. "<img />") **/protected String[] vSelfClosingTags;/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/protected String[] vNeedClosingTags;/** attributes which should be checked for valid protocols **/protected String[] vProtocolAtts;/** allowed protocols **/protected String[] vAllowedProtocols;/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/protected String[] vRemoveBlanks;/** entities allowed within html markup **/protected String[] vAllowedEntities;/// <summary>/// 是否为调试/// </summary>protected bool vDebug;public NHtmlFilter() : this(false){}public NHtmlFilter(bool debug){//List<Item> vAllowed = new List<Item>();vAllowed = new Dictionary<String, List<String>>();#region 允许通过数组vAllowed.Add("a", new List<string>() { "target", "href", "title", "class", "style" });vAllowed.Add("addr", new List<string>() { "title", "class", "style" });vAllowed.Add("address", new List<string>() { "class", "style" });vAllowed.Add("area", new List<string>() { "shape", "coords", "href", "alt" });vAllowed.Add("article", new List<string>() { });vAllowed.Add("aside", new List<string>() { });vAllowed.Add("audio", new List<string>() { "autoplay", "controls", "loop", "preload", "src", "class", "style" });vAllowed.Add("b", new List<string>() { "class", "style" });vAllowed.Add("bdi", new List<string>() { "dir" });vAllowed.Add("bdo", new List<string>() { "dir" });vAllowed.Add("big", new List<string>() { });vAllowed.Add("blockquote", new List<string>() { "cite", "class", "style" });vAllowed.Add("br", new List<string>() { });vAllowed.Add("caption", new List<string>() { "class", "style" });vAllowed.Add("center", new List<string>() { });vAllowed.Add("cite", new List<string>() { });vAllowed.Add("code", new List<string>() { "class", "style" });vAllowed.Add("col", new List<string>() { "align", "valign", "span", "width", "class", "style" });vAllowed.Add("colgroup", new List<string>() { "align", "valign", "span", "width", "class", "style" });vAllowed.Add("dd", new List<string>() { "class", "style" });vAllowed.Add("del", new List<string>() { "datetime" });vAllowed.Add("details", new List<string>() { "open" });vAllowed.Add("div", new List<string>() { "class", "style" });vAllowed.Add("dl", new List<string>() { "class", "style" });vAllowed.Add("dt", new List<string>() { "class", "style" });vAllowed.Add("em", new List<string>() { "class", "style" });vAllowed.Add("font", new List<string>() { "color", "size", "face" });vAllowed.Add("footer", new List<string>() { });vAllowed.Add("h1", new List<string>() { "class", "style" });vAllowed.Add("h2", new List<string>() { "class", "style" });vAllowed.Add("h3", new List<string>() { "class", "style" });vAllowed.Add("h4", new List<string>() { "class", "style" });vAllowed.Add("h5", new List<string>() { "class", "style" });vAllowed.Add("h6", new List<string>() { "class", "style" });vAllowed.Add("header", new List<string>() { });vAllowed.Add("hr", new List<string>() { });vAllowed.Add("i", new List<string>() { "class", "style" });vAllowed.Add("img", new List<string>() { "src", "alt", "title", "style", "width", "height", "id", "_src", "loadingclass", "class", "data-latex", "data-id", "data-type", "data-s" });vAllowed.Add("ins", new List<string>() { "datetime" });vAllowed.Add("li", new List<string>() { "class", "style" });vAllowed.Add("mark", new List<string>() { });vAllowed.Add("nav", new List<string>() { });vAllowed.Add("ol", new List<string>() { "class", "style" });vAllowed.Add("p", new List<string>() { "class", "style" });vAllowed.Add("pre", new List<string>() { "class", "style" });vAllowed.Add("s", new List<string>() { });vAllowed.Add("section", new List<string>() { });vAllowed.Add("small", new List<string>() { });vAllowed.Add("span", new List<string>() { "class", "style" });vAllowed.Add("sub", new List<string>() { "class", "style" });vAllowed.Add("sup", new List<string>() { "class", "style" });vAllowed.Add("strong", new List<string>() { "class", "style" });vAllowed.Add("table", new List<string>() { "width", "border", "align", "valign", "class", "style" });vAllowed.Add("tbody", new List<string>() { "align", "valign", "class", "style" });vAllowed.Add("td", new List<string>() { "width", "rowspan", "colspan", "align", "valign", "class", "style" });vAllowed.Add("tfoot", new List<string>() { "align", "valign", "class", "style" });vAllowed.Add("th", new List<string>() { "width", "rowspan", "colspan", "align", "valign", "class", "style" });vAllowed.Add("thead", new List<string>() { "align", "valign", "class", "style" });vAllowed.Add("tr", new List<string>() { "rowspan", "align", "valign", "class", "style" });vAllowed.Add("tt", new List<string>() { });vAllowed.Add("u", new List<string>() { });vAllowed.Add("ul", new List<string>() { "class", "style" });vAllowed.Add("video", new List<string>() { "autoplay", "controls", "loop", "preload", "src", "height", "width", "class", "style" });#endregionvDebug = debug;vTagCounts = new Dictionary<String, int>();vSelfClosingTags = new String[] { "img" };vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };vDisallowed = new String[] { "script" };vAllowedProtocols = new String[] { "http", "mailto" }; // no ftp.vProtocolAtts = new String[] { "src", "href" };vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };stripComment = true;alwaysMakeTags = true;}protected void reset(){vTagCounts = new Dictionary<String, int>();}protected void debug(String msg){if (vDebug)System.Diagnostics.Debug.WriteLine(msg);}//---------------------------------------------------------------// my versions of some PHP library functionspublic static String chr(int dec){return "" + ((char)dec);}/// <summary>/// 转换成实体字符/// </summary>/// <param name="str"></param>/// <returns></returns>public static String htmlSpecialChars(String str){str = str.Replace(P_QUOTE, "&quot;");str = str.Replace(P_LEFT_ARROW, "&lt;");str = str.Replace(P_RIGHT_ARROW, "&gt;");str = str.Replace("\n", "<br>");return str;}//---------------------------------------------------------------/*** given a user submitted input String, filter out any invalid or restricted* html.* * @param input text (i.e. submitted by a user) than may contain html* @return "clean" version of input, with only valid, whitelisted html elements allowed*/public String filter(String input){reset();String s = input;debug("************************************************");debug("              INPUT: " + input);s = escapeComments(s);debug("     escapeComments: " + s);s = balanceHTML(s);debug("        balanceHTML: " + s);s = checkTags(s);debug("          checkTags: " + s);s = processRemoveBlanks(s);debug("processRemoveBlanks: " + s);s = validateEntities(s);debug("    validateEntites: " + s);debug("************************************************\n\n");return s;}protected String escapeComments(String s){return Regex.Replace(s, P_COMMENTS, new MatchEvaluator(ConverMatchComments), RegexOptions.Singleline);}protected String regexReplace(String regex_pattern, String replacement, String s){return Regex.Replace(s, regex_pattern, replacement);}protected String balanceHTML(String s){if (alwaysMakeTags){//// try and form html//
                    s = regexReplace(P_END_ARROW, "", s);s = regexReplace(P_BODY_TO_END, "<$1>", s);s = regexReplace(P_XML_CONTENT, "$1<$2", s);}else{//// escape stray brackets//
                    s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);//// the last regexp causes '<>' entities to appear// (we need to do a lookahead assertion so that the last bracket can// be used in the next pass of the regexp)//
                    s = s.Replace(P_BOTH_ARROWS, "");}return s;}protected String checkTags(String s){//替换不允许标签foreach (var item in vDisallowed){s = Regex.Replace(s, string.Format(@"<{0}\b(.)*?>(.)+?</{0}>", item), "");}s = Regex.Replace(s, P_TAGS, new MatchEvaluator(ConverMatchTags), RegexOptions.Singleline);// these get tallied in processTag// (remember to reset before subsequent calls to filter method)foreach (String key in vTagCounts.Keys){for (int ii = 0; ii < vTagCounts[key]; ii++){s += "</" + key + ">";}}return s;}protected String processRemoveBlanks(String s){foreach (String tag in vRemoveBlanks){s = regexReplace("<" + tag + "(\\s[^>]*)?></" + tag + ">", "", s);s = regexReplace("<" + tag + "(\\s[^>]*)?/>", "", s);}return s;}private String processTag(String s){// ending tagsMatch m = P_END_TAG.Match(s);if (m.Success){string name = m.Groups[1].Value.ToLower();if (allowed(name)){if (!inArray(name, vSelfClosingTags)){if (vTagCounts.ContainsKey(name)){vTagCounts[name] = vTagCounts[name] - 1;return "</" + name + ">";}}}}// starting tagsm = P_START_TAG.Match(s);if (m.Success){String name = m.Groups[1].Value.ToLower();String body = m.Groups[2].Value;String ending = m.Groups[3].Value;//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );if (allowed(name)){String params1 = "";MatchCollection m2 = P_QUOTED_ATTRIBUTES.Matches(body);MatchCollection m3 = P_UNQUOTED_ATTRIBUTES.Matches(body);List<String> paramNames = new List<String>();List<String> paramValues = new List<String>();foreach (Match match in m2){paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)paramValues.Add(match.Groups[3].Value); //(.*?)
                        }foreach (Match match in m3){paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)paramValues.Add(match.Groups[3].Value); //([^\"\\s']+)
                        }String paramName, paramValue;for (int ii = 0; ii < paramNames.Count; ii++){paramName = paramNames[ii].ToLower();paramValue = paramValues[ii];if (allowedAttribute(name, paramName)){if (inArray(paramName, vProtocolAtts)){paramValue = processParamProtocol(paramValue);}params1 += " " + paramName + "=\"" + paramValue + "\"";}}if (inArray(name, vSelfClosingTags)){ending = " /";}if (inArray(name, vNeedClosingTags)){ending = "";}if (ending == null || ending.Length < 1){if (vTagCounts.ContainsKey(name)){vTagCounts[name] = vTagCounts[name] + 1;}else{vTagCounts.Add(name, 1);}}else{ending = " /";}return "<" + name + params1 + ending + ">";}else{return "";}}// commentsm = P_COMMENT.Match(s);if (!stripComment && m.Success){return "<" + m.Value + ">";}return "";}private String processParamProtocol(String s){s = decodeEntities(s);Match m = P_PROTOCOL.Match(s);if (m.Success){String protocol = m.Groups[1].Value;if (!inArray(protocol, vAllowedProtocols)){// bad protocol, turn into local anchor link insteads = "#" + s.Substring(protocol.Length + 1, s.Length - protocol.Length - 1);if (s.StartsWith("#//")){s = "#" + s.Substring(3, s.Length - 3);}}}return s;}private String decodeEntities(String s){s = P_ENTITY.Replace(s, new MatchEvaluator(ConverMatchEntity));s = P_ENTITY_UNICODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode));s = P_ENCODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode));s = validateEntities(s);return s;}private String validateEntities(String s){s = P_VALID_ENTITIES.Replace(s, new MatchEvaluator(ConverMatchValidEntities));s = P_VALID_QUOTES.Replace(s, new MatchEvaluator(ConverMatchValidQuotes));return s;}private static bool inArray(String s, String[] array){foreach (String item in array){if (item != null && item.Equals(s)){return true;}}return false;}private bool allowed(String name){return (vAllowed.Count == 0 || vAllowed.ContainsKey(name)) && !inArray(name, vDisallowed);}private bool allowedAttribute(String name, String paramName){return allowed(name) && (vAllowed.Count == 0 || vAllowed[name].Contains(paramName));}private String checkEntity(String preamble, String term){return ";".Equals(term) && isValidEntity(preamble)? '&' + preamble: "&amp;" + preamble;}private bool isValidEntity(String entity){return inArray(entity, vAllowedEntities);}private static string ConverMatchComments(Match match){string matchValue = "<!--" + htmlSpecialChars(match.Groups[1].Value) + "-->";return matchValue;}private string ConverMatchTags(Match match){string matchValue = processTag(match.Groups[1].Value);return matchValue;}private string ConverMatchEntity(Match match){string v = match.Groups[1].Value;int decimal1 = int.Parse(v);return chr(decimal1);}private string ConverMatchEntityUnicode(Match match){string v = match.Groups[1].Value;int decimal1 = Convert.ToInt32("0x" + v, 16);return chr(decimal1);}private string ConverMatchValidEntities(Match match){String one = match.Groups[1].Value; //([^&;]*)String two = match.Groups[2].Value; //(?=(;|&|$))return checkEntity(one, two);}private string ConverMatchValidQuotes(Match match){String one = match.Groups[1].Value; //(>|^)String two = match.Groups[2].Value; //([^<]+?)String three = match.Groups[3].Value;//(<|$)return one + regexReplace(P_QUOTE, "&quot;", two) + three;}public bool isAlwaysMakeTags(){return alwaysMakeTags;}public bool isStripComments(){return stripComment;}class Item{public string name { get; set; }public List<string> parameter { get; set; }}}

调用:

var x = new Common.NHtmlFilter(false);

string content="文本<a style='color:red;'>xxxxxxx</a><script>alert(1)</script>";

string str = x.filter(content); 

转载于:https://www.cnblogs.com/OleRookie/p/5970167.html

C# NHtmlFilter 帮你过滤Html危险脚本 防止XSS攻击相关推荐

  1. 正则表达式过滤HTML危险脚本

    正则表达式过滤HTML危险脚本1publicstringwipescript(stringhtml)2{3system.text.regularexpressions.regex regex1=new ...

  2. java 过滤xss脚本_Java Web应用程序的反跨站点脚本(XSS)过滤器

    java 过滤xss脚本 这是为Java Web应用程序编写的一个好简单的反跨站点脚本(XSS)过滤器. 它的基本作用是从请求参数中删除所有可疑字符串,然后将其返回给应用程序. 这是我以前关于该主题的 ...

  3. XSS攻击绕过过滤方法大全(转)

    XSS攻击绕过过滤方法大全(约100种) 文章目录 XSS攻击绕过过滤方法大全(约100种) 1.XSS定位器 2.XSS定位器(短) 3.无过滤绕过 4.利用多语言进行过滤绕过 5.通过JavaSc ...

  4. php过滤提交数据 防止sql注入攻击

    php过滤提交数据 防止sql注入攻击 在SQL注入攻击 中,用户通过操纵表单或 GET 查询字符串,将信息添加到数据库查询中.例如,假设有一个简单的登录数据库.这个数据库中的每个记录都有一个用户名字 ...

  5. 浅谈跨网站脚本攻击(XSS)的手段与防范(简析新浪微博XSS攻击事件)

    本文主要涉及内容: 什么是XSS XSS攻击手段和目的 XSS的防范 新浪微博攻击事件 什么是XSS 跨网站脚本(Cross-sitescripting,通常简称为XSS或跨站脚本或跨站脚本攻击)是一 ...

  6. 如何防止跨站点脚本 (XSS) 攻击完整指南

    跨站点脚本 (XSS) 攻击的完整指南.如何防止它以及 XSS 测试. 跨站点脚本 (XSS) 是每个高级测试人员都知道的最流行和易受攻击的攻击之一.它被认为是对 Web 应用程序最危险的攻击之一,也 ...

  7. vue 如何防止xss攻击 框架_LearningNotes-1/Vue/Vue中防止XSS脚本攻击 at master · axuu/LearningNotes-1 · GitHub...

    Vue中防止XSS脚本攻击 最近写了一个博客评论模块,因为引入了表情包,所以就将原来的v-text的形式,改成了v-html,也就是渲染html标签,但是这样不可不免的会带来问题,就是XSS跨站脚本攻 ...

  8. Java Web应用程序的反跨站点脚本(XSS)过滤器

    这是为Java Web应用程序编写的一个好简单的反跨站点脚本(XSS)过滤器. 它的主要作用是从请求参数中删除所有可疑字符串,然后将其返回给应用程序. 这是我以前关于该主题的帖子的改进. 您应该将其配 ...

  9. 45-互联网安全架构-Web常用攻击手段之XSS脚本SQL注入攻击

    文章目录 1. 什么是XSS攻击&XSS攻击应用场景 2. XSS脚本攻击原理分析 3. 使用过滤器防御XSS攻击 4. 使用#传递参数防御SQL注入攻击 1. 什么是XSS攻击&XS ...

最新文章

  1. 自动驾驶多目视觉感知
  2. R语言使用ggplot2包使用geom_boxplot函数绘制基础分组箱图(不同分组配置不同的箱体填充色)实战
  3. Python中的Optional和带默认值的参数
  4. mysql seq 重置_需要在Oracle中重置序列的值
  5. 右值引用和move语义?
  6. 7.4.3 矩阵极分解和平方根分解
  7. 第4章 Python 数字图像处理(DIP) - 频率域滤波2 - 复数、傅里叶级数、连续单变量函数的傅里叶变换、卷积
  8. FROONT – 超棒的可视化响应式网页设计工具
  9. 7.11牛客题(指针)
  10. 一场关于Google不作恶信条的辩论会
  11. Java 在「权力的游戏」里,能活到第几集?
  12. Ruby设计模式透析之 —— 适配器(Adapter)
  13. matlab二维函数的傅立叶变换,二维傅里叶变换和滤波(Two
  14. 基于fpga+stm32的数字示波器
  15. C++ Debug编译成XP系统下运行
  16. 常见的非关系型数据库有哪些
  17. 微信小程序云开发 实时地图显示
  18. MySQL update语句使用连表(join)
  19. java应用 cpu占用过高问题分析及解决方法
  20. .py文件与.ipynb文件互相转换

热门文章

  1. springMVC接收前端参数的方式
  2. poj-2336 Ferry Loading II(dp)
  3. 四种可变交流swap方法
  4. keytool命令总结
  5. Android之Inflate()方法用途+setContentView和inflate区别
  6. POJ 2823-Sliding Window单调队列解题报告
  7. 2019年嵌入式开发系统详细分析告诉你是否还值得去学习
  8. 在腾讯云上创建您的SQL Cluster(1)
  9. c++ split 方法(转)
  10. 学习《html5.css3.0》网页布局和样式精粹(第二天)