/// <summary> /// 获取属性过滤策略 /// </summary> /// <param name="policy"></param> /// <param name="name"></param> /// <param name="tag"></param> /// <returns></returns> public static PolicyHtmlAttribute AllowedAttribute(this IFilterPolicy policy, string name, PolicyHtmlTag tag) { var tagAttr = tag.AllowedAttributes.ContainsKey(name) ? tag.AllowedAttributes[name] : null; var globalAttr = policy.GlobalHtmlAttribute(name); if (tagAttr == null && globalAttr == null) { return(null); } var commonAttr = CommonHtmlAttribute(policy, name); return(new PolicyHtmlAttribute(name) { OnInvalid = tagAttr?.OnInvalid ?? globalAttr.OnInvalid, AllowedValues = tagAttr?.AllowedValues ?? globalAttr?.AllowedValues ?? commonAttr?.AllowedValues, AllowedRegExp = tagAttr?.AllowedRegExp ?? globalAttr?.AllowedRegExp ?? commonAttr?.AllowedRegExp }); }
/// <summary> /// 验证html标签 /// </summary> /// <param name="node"></param> /// <param name="tagName"></param> /// <param name="tag"></param> protected virtual void ValidateAction(IElement node, string tagName, PolicyHtmlTag tag) { var parentNode = node.Parent; #region 过滤样式 if ("style".Equals(tagName, StringComparison.OrdinalIgnoreCase)) { try { node.InnerHtml = CssFilter.Filters(node.InnerHtml); } catch { parentNode.RemoveChild(node); } } #endregion #region 过滤属性 for (int currentAttributeIndex = 0; currentAttributeIndex < node.Attributes.Length; currentAttributeIndex++) { var attribute = node.Attributes[currentAttributeIndex]; string name = attribute.Name, _value = attribute.Value; var attr = Policy.AllowedAttribute(name, tag); #region 如果是白名单之外的属性移除掉 if (attr == null) { node.RemoveAttribute(name); currentAttributeIndex--; continue; } #endregion #region 元素内嵌样式 if ("style".Equals(name, StringComparison.OrdinalIgnoreCase)) { try { attribute.Value = CssFilter.Filters(_value); if (string.IsNullOrWhiteSpace(attribute.Value)) { node.RemoveAttribute(name); currentAttributeIndex--; } } catch { node.RemoveAttribute(name); currentAttributeIndex--; } continue; } #endregion //如果未能通过验证,将执行指定的操作 if (!Policy.ValidateAttribute(attr, _value)) { switch (attr.OnInvalid) { case PolicyHtmlAttributeOnInvalid.RemoveTag: //删除当前的元素并退出函数 parentNode.RemoveChild(node); return; case PolicyHtmlAttributeOnInvalid.FilterTag: //删除当前节点,但保留其有效的子节点 PromoteChildren(node); return; default: //删除当前的属性,指针往回调 node.RemoveAttribute(attr.Name); currentAttributeIndex--; break; } } } #endregion //过滤当前元素的子节点 FiltersTags(node.ChildNodes); }