React中如何在dangerouslySetInnerHTML中选择性解析HTML标签
Absolutely! This is a super common need for chat apps built with React, and you absolutely can specify exactly which HTML tags to render and which to treat as plain text—all while keeping your app safe from XSS risks. Here are the best approaches to pull this off:
1. Use DOMPurify (Recommended & Secure)
DOMPurify is a battle-tested library designed specifically to sanitize HTML and prevent XSS attacks. It lets you define a whitelist of allowed tags/attributes, and automatically strips or escapes anything not on your list (like <script> or <link>).
Step-by-Step Implementation:
- Install the library:
npm install dompurify # or yarn add dompurify
- Use it in your chat message component:
import DOMPurify from 'dompurify'; import { useEffect, useState } from 'react'; const ChatMessage = ({ content }) => { const [sanitizedContent, setSanitizedContent] = useState(''); useEffect(() => { // Define exactly which tags you want to allow const allowedTags = ['strong', 'em', 'h2', 'p', 'br']; // Optional: Define allowed attributes for specific tags (e.g., href for <a> if needed) const allowedAttributes = {}; // Configure DOMPurify to use your whitelist const purifyConfig = { ADD_TAGS: allowedTags, ALLOWED_ATTR: allowedAttributes, // Explicitly forbid dangerous tags as an extra layer of safety FORBID_TAGS: ['script', 'link', 'iframe', 'style'], }; // Sanitize the incoming content const cleanContent = DOMPurify.sanitize(content, purifyConfig); setSanitizedContent(cleanContent); }, [content]); // Render the sanitized HTML safely return ( <div className="chat-message-content" dangerouslySetInnerHTML={{ __html: sanitizedContent }} /> ); }; export default ChatMessage;
How It Works:
- Tags like
<strong>Hello</strong>will render as bold text. - Dangerous tags like
<script>alert('XSS')</script>or<link rel="stylesheet" href="malicious.css">will be converted to plain text, so they don't execute or load anything. - DOMPurify handles edge cases (like nested tags or malformed HTML) that manual solutions often miss.
2. Manual Sanitization (Not Recommended for Production)
If you want to avoid third-party libraries, you can write a basic sanitizer using regex—but this is risky because HTML is complex, and regex can't fully handle all edge cases (leading to potential XSS holes). Here's a simple example:
const sanitizeHtml = (rawContent) => { // First, escape all HTML tags to plain text let sanitized = rawContent.replace(/</g, '<').replace(/>/g, '>'); // Define your allowed tags and convert them back to actual HTML const allowedTags = ['strong', 'em', 'h2']; allowedTags.forEach(tag => { sanitized = sanitized.replace(new RegExp(`<${tag}>`, 'g'), `<${tag}>`); sanitized = sanitized.replace(new RegExp(`</${tag}>`, 'g'), `</${tag}>`); }); return sanitized; }; // Use in your component const ChatMessage = ({ content }) => { const sanitizedContent = sanitizeHtml(content); return ( <div className="chat-message-content" dangerouslySetInnerHTML={{ __html: sanitizedContent }} /> ); };
Caveats:
- This won't handle tags with attributes (e.g.,
<h2 class="large">will stay as plain text). - Nested tags (e.g.,
<strong><em>Text</em></strong>) might not render correctly. - It's far more vulnerable to XSS attacks than DOMPurify.
Final Notes
Yes, you absolutely can specify which tags to parse and which to ignore. For production apps, DOMPurify is the way to go—it's secure, maintained, and flexible enough to fit your exact requirements.
内容的提问来源于stack exchange,提问作者MitchEff

