العودة إلى التحديثات
New releaseSep 22, 2026

java-html-sanitizer v20260921.1

يأخذ HTML من طرف ثالث وينتج HTML آمنًا لتضمينه في تطبيق الويب الخاص بك. سريع وسهل التكوين.

مشاركة

OWASP Java HTML Sanitizer

Java CI with Maven Coverage Status CII Best Practices Maven Central

أداة تعقيم HTML سريعة وسهلة التهيئة مكتوبة بلغة Java تتيح لك تضمين HTML من كتابة أطراف ثالثة في تطبيق الويب الخاص بك مع الحماية من هجمات XSS.

الاعتماد الحالي هو على JSR 305. أما بقية ملفات jar فهي مطلوبة فقط لمجموعة الاختبارات. اعتماد JSR 305 هو اعتماد فقط في زمن الترجمة، مطلوب فقط للتعليقات التوضيحية.

هذا الكود كُتب مع مراعاة أفضل ممارسات الأمان، وله مجموعة اختبارات واسعة، وخضع لمراجعة أمان مواجهة.

جدول المحتويات

البدء

البدء يتضمن إرشادات حول كيفية البدء مع Maven أو بدونه.

السياسات المُجهزة مسبقًا

يمكنك استخدام السياسات المُجهزة مسبقًا:

PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
String safeHTML = policy.sanitize(untrustedHTML);

صياغة سياسة

توضح الاختبارات كيفية تكوين سياسة خاصة بك:

PolicyFactory policy = new HtmlPolicyBuilder()
    .allowElements("a")
    .allowUrlProtocols("https")
    .allowAttributes("href").onElements("a")
    .requireRelNofollowOnLinks()
    .toFactory();
String safeHTML = policy.sanitize(untrustedHTML);

السياسات المخصصة

يمكنك كتابة سياسات مخصصة للقيام بأشياء مثل تغيير عناوين h1 إلى عناصر div مع فئة معينة:

PolicyFactory policy = new HtmlPolicyBuilder()
    .allowElements("p")
    .allowElements(
        (String elementName, List<String> attrs) -> {
          // إضافة سمة فئة.
          attrs.add("class");
          attrs.add("header-" + elementName);
          // إرجاع elementName للإشارة، أو null للحذف.
          return "div";
        }, "h1", "h2", "h3", "h4", "h5", "h6")
    .toFactory();
String safeHTML = policy.sanitize(untrustedHTML);

يُرجى ملاحظة أن العناصر "a" و "font" و "img" و "input" و "span" تحتاج إلى أن تكون مدرجة صراحة في القائمة البيضاء باستخدام طريقة allowWithoutAttributes() إذا كنت تريد السماح بمرورها عبر المرشح عندما لا تتضمن هذه العناصر أي سمات.

سياسات السمات تسمح أيضًا بتشغيل كود مخصص. إضافة سياسة سمة لن تُضعف أي سياسة افتراضية مثل فحص style أو عناوين URL.

new HtmlPolicyBuilder = new HtmlPolicyBuilder()
    .allowElement("div", "span")
    .allowAttributes("data-foo")
        .matching(
            (String elementName, String attributeName, String value) -> {
              // إرجاع قيمة السمة أو null للحذف.
            })
        .onElements("div", "span")
    .build()

المعالجات المسبقة

المعالجات المسبقة تسمح بإدراج نص وتغييرات هيكلية كبيرة.

new HtmlPolicyBuilder = new HtmlPolicyBuilder()
    // استخدام معالج مسبق للتوافق مع الإصدارات السابقة
    // لعنصر <plaintext> الذي ...
    .withPreprocessor(
        (HtmlStreamEventReceiver r) -> {
          // تزويد المستخدم بمعلومات حول الروابط قبل النقر عليها.
          // قبل:                       <a href="https://example.com/...">
          // بعد:  (https://example.com) <a href="https://example.com/...">
          return new HtmlStreamEventReceiverWrapper(r) {
            @Override public void openTag(String elementName, List<String> attrs) {
              if ("a".equals(elementName)) {
                for (int i = 0, n = attrs.size(); i < n; i += 2) {
                  if ("href".equals(attrs.get(i)) {
                    String url = attrs.get(i + 1);
                    String origin;
                    try {
                      URI uri = new URI(url);
                      String scheme = uri.getScheme();
                      String authority = uri.getRawAuthority();
                      if (scheme == null && authority == null) {
                        origin = null;
                      } else {
                        origin = (scheme != null ? scheme + ":" : "")
                               + (authority != null ? "//" + authority : "");
                      }
                    } catch (URISyntaxException ex) {
                      origin = "about:invalid";
                    }
                    if (origin != null) {
                      text(" (" + origin + ") ");
                    }
                  }
                }
              }
              super.openTag(elementName, attrs);
            }
          };
        }
    .allowElement("a")
    ...
    .build()

المعالجة المسبقة تحدث قبل تطبيق السياسة، لذا لا يمكن أن تؤثر على أمان المخرجات.

القياس عن بُعد

عندما ترفض سياسة عنصرًا أو سمة، فإنها تُخطر HtmlChangeListener.

يمكنك استخدام هذا لتتبع اتجاهات انتهاكات السياسة ومعرفة متى يحاول شخص ما اختراق أمانك.

PolicyFactory myPolicyFactory = ...;
// إذا كنت بحاجة إلى ربط التقارير ببعض السياقات، يمكنك فعل ذلك.
MyContextClass myContext = ...;

String sanitizedHtml = myPolicyFactory.sanitize(
    unsanitizedHtml,
    new HtmlChangeListener<MyContextClass>() {
      @Override
      public void discardedTag(MyContextClass context, String elementName) {
        // ...
      }
      @Override
      public void discardedAttributes(
          MyContextClass context, String elementName, String... attributeNames) {
        // ...
      }
    },
    myContext);

ملاحظة: إذا تم تعقيم سلسلة بدون إشعارات تغيير، فهذا لا يعني أن السلسلة المُدخلة آمنة بالضرورة. استخدم فقط مخرجات المُعقّم.

يضمن المُعقّم أن المخرجات هي ضمن مجموعة فرعية من HTML ستتفق عليها برامج تحليل HTML الشائعة على معناها، لكن عدم وجود إشعارات لا يعني أن المُدخل هو ضمن هذه المجموعة الفرعية، بل فقط أنه لا يحتوي على عناصر أو سمات تمت إزالتها.

انظر "لماذا التعقيم بدلاً من التحقق؟" للمزيد حول هذا الموضوع.

أسئلة؟

إذا كنت ترغب في الإبلاغ عن ثغرة، يُرجى الاطلاع على قواعد مراجعة الهجوم.

اشترك في القائمة البريدية ليصلك إشعار بالثغرات المعروفة Vulnerabilities والتحديثات المهمة.

المساهمة

إذا كنت ترغب في المساهمة، يُرجى التواصل مع @mvsamuel أو @manicode.

نرحب بـ تقارير المشكلات وطلبات السحب (PRs). طلبات السحب التي تُغير السلوك أو تُضيف وظائف يجب أن تتضمن اختبارات إيجابية وسلبية.

يُرجى العلم أن المساهمات تخضع لـ رخصة Apache 2.0.

الإشادات

شكر لكل من ساعد بالنقد والكود

الفئات